diff --git a/README.md b/README.md index 81eafca..15451e2 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ Detects a programming language from a given string. ## Detectable languages -| Languages | | | | -| --------- | ---------- | ------ | ------ | -| C | Dockerfile | Julia | Python | -| C++ | Go | Kotlin | Ruby | -| C# | HTML | Lua | Rust | -| Clojure | Java | Pascal | SQL | -| CSS | Javascript | PHP | Yaml | +| Languages | | | | | +| --------- | ---------- | ---------- | ------ | ---- | +| C | Dockerfile | Javascript | Pascal | SQL | +| C++ | Elixir | Julia | PHP | YAML | +| C# | Go | Kotlin | Python | | +| Clojure | HTML | Lua | Ruby | | +| CSS | Java | Markdown | Rust | | ## Install @@ -39,32 +39,34 @@ or via a CDN (unpkg or jsdelivr) ```js import flourite from 'flourite'; -const code = flourite('printf("Hello World");'); +const code = flourite('cout << "Hello world" << endl;'); // { -// language: 'C', +// language: 'C++', // statistics: { -// C: 5, +// C: 0, // Clojure: 0, -// 'C++': 0, -// 'C#': 0, +// 'C++': 5, // CSS: 0, +// 'C#': 0, // Dockerfile: 0, +// Elixir: 0, // Go: 0, // HTML: 0, // Java: 0, // Javascript: 0, -// Julia: 0, +// Julia: 2, // Kotlin: 0, -// Lua: -20, +// Lua: 2, +// Markdown: 0, // Pascal: 0, // PHP: 0, // Python: 0, // Ruby: 0, // Rust: 0, // SQL: 0, +// Unknown: 1, // YAML: 0, -// Unknown: 1 // }, // linesOfCode: 1 // } diff --git a/src/index.ts b/src/index.ts index 810cd74..a8d2873 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { CPP } from './languages/cpp'; import { CS } from './languages/cs'; import { CSS } from './languages/css'; import { Dockerfile } from './languages/dockerfile'; +import { Elixir } from './languages/elixir'; import { Go } from './languages/go'; import { HTML } from './languages/html'; import { Java } from './languages/java'; @@ -30,6 +31,7 @@ const languages: Record = { 'C#': CS, CSS, Dockerfile, + Elixir, Go, HTML, Java, diff --git a/src/languages/elixir.ts b/src/languages/elixir.ts new file mode 100644 index 0000000..ab8c39c --- /dev/null +++ b/src/languages/elixir.ts @@ -0,0 +1,21 @@ +import type { LanguagePattern } from '../types'; + +export const Elixir: LanguagePattern[] = [ + // Modules + { pattern: /^\s*defmodule\s+.+\s+do$/, type: 'meta.module' }, + // Alias + { pattern: /\s*alias\s+.+as:.+/, type: 'keyword.other' }, + // IO.puts() + { pattern: /IO\.puts.+/, type: 'keyword.print' }, + // Anonymous func + { pattern: /fn\s+[A-Za-z0-9_:<>()]+\s+->\s+.+(end)?$/, type: 'keyword.function' }, + { pattern: /^\s*(def|defp)\s+.+\s+do$/, type: 'keyword.function' }, + { pattern: /^\s*(if|unless|cond|case|try|defimpl|defprotocol)\s+.+\s+do$/, type: 'keyword.control' }, + { pattern: /^\s*defstruct\s+/, type: 'keyword' }, + // Spec + { pattern: /^\s*@spec\s+.+::.+/, type: 'macro' }, + // Lists + { pattern: /\{:.+,.+\}/, type: 'constant.array' }, + // Maps + { pattern: /%\{(.+(=>|:).+(,)?){1,}\}/, type: 'constant.dictionary' }, +]; diff --git a/src/languages/markdown.ts b/src/languages/markdown.ts index 946083d..14a8085 100644 --- a/src/languages/markdown.ts +++ b/src/languages/markdown.ts @@ -2,25 +2,19 @@ import type { LanguagePattern } from '../types'; export const Markdown: LanguagePattern[] = [ // headings - { pattern: /(#){1,6} .+/, type: 'macro', nearTop: true }, + { pattern: /^(#){2,6}\s.+/, type: 'keyword' }, // headings alternate syntax - { pattern: /^(?!!)(=|-){2,}(?)$/, type: 'meta.module', nearTop: true }, - // bold - { pattern: /(\w*(?!\/)(\*\*)\w+(\*\*)\w*)|(\w*(__)\w+(__)\w*)/, type: 'macro', nearTop: true }, - // italic - { pattern: /(^.*(\*).+(\*)(?)$/, type: 'meta.module' }, // images - { pattern: /!\[.+\]\(.+\)/, type: 'macro', nearTop: true }, - // links - { pattern: /\[.+\]\(.+\)/, type: 'macro', nearTop: true }, + { pattern: /(!)?\[.+\]\(.+\)/, type: 'keyword' }, // links 2 - { pattern: /\[.+\]\[.+\]/, type: 'macro', nearTop: true }, + { pattern: /\[.+\]\[.+\]/, type: 'keyword' }, // links 3 - { pattern: /\[.+\]:\s? .*)+/, type: 'macro', nearTop: true }, - // inline code - { pattern: /.*`.+`.*/, type: 'meta.module', nearTop: true }, + { pattern: /^(> .*)+/, type: 'macro' }, + // code block + { pattern: /^```([A-Za-z0-9#_]+)?$/, type: 'keyword' }, + // frontmatter + { pattern: /^---$/, type: 'meta.module', nearTop: true }, ]; diff --git a/tests/cpp.test.ts b/tests/cpp.test.ts index 2df6c17..d9ac51b 100644 --- a/tests/cpp.test.ts +++ b/tests/cpp.test.ts @@ -15,6 +15,7 @@ test('hello world', () => { CSS: 0, 'C#': 0, Dockerfile: 0, + Elixir: 0, Go: 0, HTML: 0, Java: 0, @@ -22,6 +23,7 @@ test('hello world', () => { Julia: 2, Kotlin: 0, Lua: 2, + Markdown: 0, Pascal: 0, PHP: 0, Python: 0, @@ -30,7 +32,6 @@ test('hello world', () => { SQL: 0, Unknown: 1, YAML: 0, - Markdown: 0, }); assert.equal(code.linesOfCode, 1); }); diff --git a/tests/cs.test.ts b/tests/cs.test.ts index bb02213..9dc2217 100644 --- a/tests/cs.test.ts +++ b/tests/cs.test.ts @@ -16,6 +16,7 @@ test('hello world', () => { 'C#': 10, CSS: 0, Dockerfile: 0, + Elixir: 0, Go: -39, HTML: 0, Java: -40, @@ -23,6 +24,7 @@ test('hello world', () => { Julia: 5, Kotlin: 0, Lua: -20, + Markdown: 0, Pascal: 0, PHP: 0, Python: 0, @@ -31,7 +33,6 @@ test('hello world', () => { SQL: 0, Unknown: 1, YAML: 0, - Markdown: 0, }); assert.equal(code.linesOfCode, 2); }); diff --git a/tests/elixir.test.ts b/tests/elixir.test.ts new file mode 100644 index 0000000..f8f3231 --- /dev/null +++ b/tests/elixir.test.ts @@ -0,0 +1,226 @@ +import { test } from 'uvu'; +import * as assert from 'uvu/assert'; +import detectLang from '../src'; + +test('hello world', () => { + const code = detectLang(`IO.puts :stderr, "Goodbye, World!"`); + assert.equal(code.language, 'Elixir'); +}); + +test('fizz buzz', () => { + const code = detectLang(`defmodule FizzBuzz do + def fizzbuzz(n) when rem(n, 15) == 0, do: "FizzBuzz" + def fizzbuzz(n) when rem(n, 5) == 0, do: "Buzz" + def fizzbuzz(n) when rem(n, 3) == 0, do: "Fizz" + def fizzbuzz(n), do: n +end + +Enum.each(1..100, &IO.puts FizzBuzz.fizzbuzz &1)`); + assert.equal(code.language, 'Elixir'); +}); + +test('anagrams', () => { + const code = detectLang(`defmodule Anagrams do + def find(file) do + File.read!(file) + |> String.split + |> Enum.group_by(fn word -> String.codepoints(word) |> Enum.sort end) + |> Enum.group_by(fn {_,v} -> length(v) end) + |> Enum.max + |> print + end + + defp print({_,y}) do + Enum.each(y, fn {_,e} -> Enum.sort(e) |> Enum.join(" ") |> IO.puts end) + end +end + +Anagrams.find("unixdict.txt")`); + assert.equal(code.language, 'Elixir'); +}); + +test('bubble sort', () => { + const code = detectLang(`defmodule Sort do + def bsort(list) when is_list(list) do + t = bsort_iter(list) + + if t == list, do: t, else: bsort(t) + end + + def bsort_iter([x, y | t]) when x > y, do: [y | bsort_iter([x | t])] + def bsort_iter([x, y | t]), do: [x | bsort_iter([y | t])] + def bsort_iter(list), do: list +end`); + assert.equal(code.language, 'Elixir'); +}); + +test('heap sort', () => { + const code = detectLang(`defmodule Sort do + def heapSort(list) do + len = length(list) + heapify(List.to_tuple(list), div(len - 2, 2)) + |> heapSort(len-1) + |> Tuple.to_list + end + + defp heapSort(a, finish) when finish > 0 do + swap(a, 0, finish) + |> siftDown(0, finish-1) + |> heapSort(finish-1) + end + defp heapSort(a, _), do: a + + defp heapify(a, start) when start >= 0 do + siftDown(a, start, tuple_size(a)-1) + |> heapify(start-1) + end + defp heapify(a, _), do: a + + defp siftDown(a, root, finish) when root * 2 + 1 <= finish do + child = root * 2 + 1 + if child + 1 <= finish and elem(a,child) < elem(a,child + 1), do: child = child + 1 + if elem(a,root) < elem(a,child), + do: swap(a, root, child) |> siftDown(child, finish), + else: a + end + defp siftDown(a, _root, _finish), do: a + + defp swap(a, i, j) do + {vi, vj} = {elem(a,i), elem(a,j)} + a |> put_elem(i, vj) |> put_elem(j, vi) + end +end + +(for _ <- 1..20, do: :rand.uniform(20)) |> IO.inspect |> Sort.heapSort |> IO.inspect`); + assert.equal(code.language, 'Elixir'); +}); + +test('merge sort', () => { + const code = detectLang(`defmodule Sort do + def merge_sort(list) when length(list) <= 1, do: list + def merge_sort(list) do + {left, right} = Enum.split(list, div(length(list), 2)) + :lists.merge( merge_sort(left), merge_sort(right)) + end +end`); + assert.equal(code.language, 'Elixir'); +}); + +test('quick sort', () => { + const code = detectLang(`defmodule Sort do + def qsort([]), do: [] + def qsort([h | t]) do + {lesser, greater} = Enum.split_with(t, &(&1 < h)) + qsort(lesser) ++ [h] ++ qsort(greater) + end +end`); + assert.equal(code.language, 'Elixir'); +}); + +test('ludic numbers', () => { + const code = detectLang(`defmodule Ludic do + def numbers(n \\ 100000) do + [h|t] = Enum.to_list(1..n) + numbers(t, [h]) + end + + defp numbers(list, nums) when length(list) < hd(list), do: Enum.reverse(nums, list) + defp numbers([h|_]=list, nums) do + Enum.drop_every(list, h) |> numbers([h | nums]) + end + + def task do + IO.puts "First 25 : #{inspect numbers(200) |> Enum.take(25)}" + IO.puts "Below 1000: #{length(numbers(1000))}" + tuple = numbers(25000) |> List.to_tuple + IO.puts "2000..2005th: #{ inspect for i <- 1999..2004, do: elem(tuple, i) }" + ludic = numbers(250) + triple = for x <- ludic, x+2 in ludic, x+6 in ludic, do: [x, x+2, x+6] + IO.puts "Triples below 250: #{inspect triple, char_lists: :as_lists}" + end +end + +Ludic.task`); + assert.equal(code.language, 'Elixir'); +}); + +test('happy numbers', () => { + const code = detectLang(`defmodule Happy do + def task(num) do + Process.put({:happy, 1}, true) + Stream.iterate(1, &(&1+1)) + |> Stream.filter(fn n -> happy?(n) end) + |> Enum.take(num) + end + + defp happy?(n) do + sum = square_sum(n, 0) + val = Process.get({:happy, sum}) + if val == nil do + Process.put({:happy, sum}, false) + val = happy?(sum) + Process.put({:happy, sum}, val) + end + val + end + + defp square_sum(0, sum), do: sum + defp square_sum(n, sum) do + r = rem(n, 10) + square_sum(div(n, 10), sum + r*r) + end +end + +IO.inspect Happy.task(8)`); + assert.equal(code.language, 'Elixir'); +}); + +test('floyd warshall', () => { + const code = detectLang(`defmodule Floyd_Warshall do + def main(n, edge) do + {dist, next} = setup(n, edge) + {dist, next} = shortest_path(n, dist, next) + print(n, dist, next) + end + + defp setup(n, edge) do + big = 1.0e300 + dist = for i <- 1..n, j <- 1..n, into: %{}, do: {{i,j},(if i==j, do: 0, else: big)} + next = for i <- 1..n, j <- 1..n, into: %{}, do: {{i,j}, nil} + Enum.reduce(edge, {dist,next}, fn {u,v,w},{dst,nxt} -> + { Map.put(dst, {u,v}, w), Map.put(nxt, {u,v}, v) } + end) + end + + defp shortest_path(n, dist, next) do + (for k <- 1..n, i <- 1..n, j <- 1..n, do: {k,i,j}) + |> Enum.reduce({dist,next}, fn {k,i,j},{dst,nxt} -> + if dst[{i,j}] > dst[{i,k}] + dst[{k,j}] do + {Map.put(dst, {i,j}, dst[{i,k}] + dst[{k,j}]), Map.put(nxt, {i,j}, nxt[{i,k}])} + else + {dst, nxt} + end + end) + end + + defp print(n, dist, next) do + IO.puts "pair dist path" + for i <- 1..n, j <- 1..n, i != j, + do: :io.format "~w -> ~w ~4w ~s~n", [i, j, dist[{i,j}], path(next, i, j)] + end + + defp path(next, i, j), do: path(next, i, j, [i]) |> Enum.join(" -> ") + + defp path(_next, i, i, list), do: Enum.reverse(list) + defp path(next, i, j, list) do + u = next[{i,j}] + path(next, u, j, [u | list]) + end +end + +edge = [{1, 3, -2}, {2, 1, 4}, {2, 3, 3}, {3, 4, 2}, {4, 2, -1}] +Floyd_Warshall.main(4, edge)`); + assert.equal(code.language, 'Elixir'); +}); + +test.run(); diff --git a/tests/large.test.ts b/tests/large.test.ts index f8e8251..8acb3d5 100644 --- a/tests/large.test.ts +++ b/tests/large.test.ts @@ -664,6 +664,7 @@ test('large input', () => { 'C#': 19, CSS: 0, Dockerfile: 0, + Elixir: 0, Go: 0, HTML: 0, Java: -832, @@ -671,6 +672,7 @@ test('large input', () => { Julia: 24, Kotlin: 0, Lua: -1820, + Markdown: 0, Pascal: 0, PHP: -318, Python: -140, @@ -679,7 +681,6 @@ test('large input', () => { SQL: 24, Unknown: 1, YAML: 4, - Markdown: 9, }); assert.equal(code.linesOfCode, 356); }); diff --git a/tests/markdown.test.ts b/tests/markdown.test.ts index e0c535e..46f401c 100644 --- a/tests/markdown.test.ts +++ b/tests/markdown.test.ts @@ -2,11 +2,6 @@ import { test } from 'uvu'; import * as assert from 'uvu/assert'; import detectLang from '../src/index'; -test('heading 1', () => { - const code = detectLang('# Heading level 1'); - assert.equal(code.language, 'Markdown'); -}); - test('heading 2', () => { const code = detectLang('## Heading level 2'); assert.equal(code.language, 'Markdown'); @@ -42,37 +37,6 @@ test('heading 2 alternate syntax', () => { assert.equal(code.language, 'Markdown'); }); -test('bold syntax 1', () => { - const code = detectLang('**This text will be bold**'); - assert.equal(code.language, 'Markdown'); -}); - -test('bold syntax 2', () => { - const code = detectLang('__This will also be bold__'); - assert.equal(code.language, 'Markdown'); -}); - -test('italic syntax 1', () => { - const code = detectLang('*This text will be italic*'); - assert.equal(code.language, 'Markdown'); -}); - -test('italic syntax 2', () => { - const code = detectLang('_This will also be italic_'); - assert.equal(code.language, 'Markdown'); -}); - -test('list syntax 1', () => { - const code = detectLang(`* Item 1`); - assert.equal(code.language, 'Markdown'); -}); - -// FIXME: Conflicts with YAML -test.skip('list syntax 2', () => { - const code = detectLang(`- Item 1`); - assert.equal(code.language, 'Markdown'); -}); - test('images', () => { const code = detectLang(`![GitHub Logo](/images/logo.png)`); assert.equal(code.language, 'Markdown'); @@ -104,892 +68,403 @@ test('blockquotes', () => { assert.equal(code.language, 'Markdown'); }); -test('inline code', () => { - const code = detectLang('I think you should use an`` element here instead.'); - assert.equal(code.language, 'Markdown'); -}); - -test.skip('example 1', () => { +test('example 1', () => { const code = detectLang(`# Changelog - All notable changes to this project will be documented in this file. - - The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - - - ## [12.2.0] - 2021-08-02 - ### Added - - Ordered lists: add order value to token info. - - ### Fixed - - Always suffix indented code block with a newline, #799. - - - ## [12.1.0] - 2021-07-01 - ### Changed - - Updated CM spec compatibility to 0.30. - - - ## [12.0.6] - 2021-04-16 - ### Fixed - - Newline in \`alt\` should be rendered, #775. - - - ## [12.0.5] - 2021-04-15 - ### Fixed - - HTML block tags with \`===\` inside are no longer incorrectly interpreted as headers, #772. - - Fix table/list parsing ambiguity, #767. - - - ## [12.0.4] - 2020-12-20 - ### Fixed - - Fix crash introduced in \`12.0.3\` when processing strikethrough (\`~~\`) and similar plugins, #742. - - Avoid fenced token mutation, #745. - - - ## [12.0.3] - 2020-12-07 - ### Fixed - - \`[]()\` is no longer a valid link. - - \`[](url (xxx())\` is no longer a valid link. - - \`[](url xxx)\` is no longer a valid link. - - Fix performance issues when parsing links (#732, #734), backticks, (#733, #736), - emphases (#735), and autolinks (#737). - - Allow newline in \`\` in an inline context. - - Allow \`\` html tag to appear in an inline context. - - - ## [12.0.2] - 2020-10-23 - ### Fixed - - Three pipes (\`|\n|\n|\`) are no longer rendered as a table with no columns, #724. - - - ## [12.0.1] - 2020-10-19 - ### Fixed - - Fix tables inside lists indented with tabs, #721. - - - ## [12.0.0] - 2020-10-14 - ### Added - - \`.gitattributes\`, force unix eol under windows, for development. - - ### Changed - - Added 3rd argument to \`highlight(code, lang, attrs)\`, #626. - - Rewrite tables according to latest GFM spec, #697. - - Use \`rollup.js\` to browserify sources. - - Drop \`bower.json\` (bower reached EOL). - - Deps bump. - - Tune \`specsplit.js\` options. - - Drop \`Makefile\` in favour of npm scrips. - - ### Fixed - - Fix mappings for table rows (amended fix made in 11.0.1), #705. - - \`%25\` is no longer decoded in beautified urls, #720. - - - ## [11.0.1] - 2020-09-14 - ### Fixed - - Fix blockquote lazy newlines, #696. - - Fix missed mappings for table rows, #705. - - - ## [11.0.0] - 2020-05-20 - ### Changed - - Bumped \`linkify-it\` to 3.0.0, #661 + allow unlimited \`.\` inside links. - - Dev deps bump. - - Switch to \`nyc\` for coverage reports. - - Partially moved tasks from Makefile to npm scripts. - - Automate web update on npm publish. - - ### Fixed - - Fix em- and en-dashes not being typographed when separated by 1 char, #624. - - Allow opening quote after another punctuation char in typographer, #641. - - Assorted wording & typo fixes. - - - ## [10.0.0] - 2019-09-11 - ### Security - - Fix quadratic parse time for some combinations of pairs, #583. Algorithm is - now similar to one in reference implementation. - - ### Changed - - Minor internal structs change, to make pairs parse more effective (cost is - linear now). If you use external "pairs" extensions, you need sync those with - "official ones". Without update, old code will work, but can cause invalid - result in rare case. This is the only reason of major version bump. With high probability you don't need to change your code, only update version dependency. - - Updated changelog format. - - Deps bump. - - - ## [9.1.0] - 2019-08-11 - ### Changed - - Remove extra characters from line break check. Leave only 0x0A & 0x0D, as in - CommonMark spec, #581. - - - ## [9.0.1] - 2019-07-12 - ### Fixed - - Fix possible corruption of open/close tag levels, #466 - - - ## [9.0.0] - 2019-07-09 - ### Changed - - Updated CM spec compatibility to 0.29. - - Update Travis-CI node version to actual (8 & latest). - - Deps bump. - - - ## [8.4.2] - 2018-02-15 - ### Fixed - - Fix \`--no-html\` CLI option, #476. - - - ## [8.4.1] - 2018-02-15 - ### Fixed - - Fix smartquotes around softbreaks, #430. - - - ## [8.4.0] - 2017-08-24 - ### Changed - - Updated CM spec compatibility to 0.28. - - - ## [8.3.2] - 2017-08-03 - ### Fixed - - Fix blockquote termination inside lists, #386. - - - ## [8.3.1] - 2017-03-06 - ### Fixed - - Fix blockquote termination by list item, #338. - - - ## [8.3.0] - 2017-02-16 - ### Changed - - Remove tabs at the beginning of the line in paragraphs. - - Better error message for bad input type, #324. - - ### Fixed - - Fix table indentation issues, #325, #224. - - Fix blockquote termination inside indented lists, #329. - - - ## [8.2.2] - 2016-12-15 - ### Added - - Add \`-o\` / \`--output\` option to CLI, #312. - - - ## [8.2.1] - 2016-12-02 - ### Fixed - - Add missed h2..h6 to whitelisted block tags. - - - ## [8.2.0] - 2016-12-01 - ### Changed - - Updated CM spec compatibility to 0.27 (no significant changes). - - ### Fixed - - Fix backticks handle inside tables, #303. - - Fix edge case for fenced blocks with \`~~~\` in info, #301. - - Fix fallback to reference if link is not valid, #302. - - - ## [8.1.0] - 2016-11-03 - ### Changed - - Make link parse helpers (\`md.helpers\`) pluggable, #299. - - - ## [8.0.1] - 2016-10-18 - ### Fixed - - Tables: allow tab characters in markup - - - ## [8.0.0] - 2016-09-16 - ### Changed - - Benchmarks src cleanup. - - Remove testing in old nodes (but still use es5). - - Updated CM spec compatibility to 0.26 (see list below): - - Two consecutive newlines no longer terminate a list. - - Ordered list terminating a paragraph can now only start with 1. - - Adjust emphasis algorithm (\`*foo**bar**baz*\` is now parsed as \`\` - inside \`\`). - - Fix tab width calculation inside lists and blockquotes. - - - ## [7.0.1] - 2016-08-16 - ### Fixed - - Fence renderer: fix concat of class array, #276. - - Code renderer: do not render double space before attrs, #275. - - Replacer: disable replacements inside autolinks, #272. - - - ## [7.0.0] - 2016-06-22 - ### Changed - - Bump \`linkify-it\` dependency to 2.0.0. \`---\` no longer terminates - autodetected links by default. \`md.linkifier.set('---', true)\` will return old - behaviour. - - Major version bumped, because internals or \`linkify-it\` was changed. - You will not be affected anyhow, if not used direct access to - \`require('linkify-it/re')\` for customizations. - - - ## [6.1.1] - 2016-06-21 - ### Changed - - Render \`code_inline\` & \`code_block\` attributes if exist. - - - ## [6.1.0] - 2016-06-19 - ### Changed - - Updated \`fence\` renderer to not mutate token. Token stream should be - immutable after renderer call. - - - ## [6.0.5] - 2016-06-01 - ### Fixed - - Process \`\r\` the same way as \`\n\` and \`\r\n\\\`, #252. - - - ## [6.0.4] - 2016-05-30 - ### Added - - Added \`Token.attrGet()\` method for convenience, #251. - - - ## [6.0.3] - 2016-05-30 - ### Security - - Security fix: possible ReDOS in \`linkify-it\` (forced bump of \`linkify-it\` & - \`uc-micro\` dependencies). New installs will use fixed packages automatically, - but we bumped \`markdown-it\` version for sure & for web builds. - - - ## [6.0.2] - 2016-05-16 - ### Fixed - - Fix: should not escape twice content of image alt attribute, #246. - - - ## [6.0.1] - 2016-04-02 - ### Fixed - - Improve support of missing values in tables, #224. - - - ## [6.0.0] - 2016-02-11 - ### Changed - - Maintenance release. Version bump caused by notable changes in CM spec - (multiline setext headers, no spaces inside links, ...). API was not changed. - - Fit CM 0.24 spec requirements. - - ### Fixed - - Fixed nesting limit check in inline blocks, #197. - - Fixed posible tail loss in CLI ouput. - - - ## [5.1.0] - 2016-01-07 - ### Added - - Token: added \`.attrSet()\` & \`.attrJoin()\` methods. - - Highlighter: allow wrapper override (if result starts with " source in demo. - - ### Changed - - Moved \`normalizeReference()\` to utils. - - ### Fixed - - Fixed hang on long vertical list of links. Appeared in 3.0.5. See #54 for - details. Thanks to @fengmk2 for report! - - Table lines now can have escaped pipe char \`|\` (#5). - - - ## [3.0.5] - 2015-02-06 - ### Changed - - Significantly improved tests coverage (with dead code removal and other - related things). - - ### Fixed - - Fixed link validator - could skip some kind of javascript links with uppercase - digital entities (thanks to @opennota) - - - ## [3.0.4] - 2015-01-13 - ### Changed - - Improved errors processing in url normalizer (for broken sequences). - - Improved nesting limit processing in inline parser. - - Reorganized tests & improved coverage. - - Show inline diffs for failed tests. - - - ## [3.0.3] - 2015-01-11 - ### Fixed - - Fixed punctuation check in emphasis. - - - ## [3.0.2] - 2015-01-09 - ### Fixed - - Allow dashes in HTML tag names (needed for custom HTML tags). - - - ## [3.0.1] - 2015-01-07 - ### Changed - - Added # to terminator chars. - - ### Fixed - - Improved link encoder - fix invalid surrogates to avoid errors. - - - ## [3.0.0] - 2015-01-04 - ### Changed - - Big split. All "rare" rules moved to external plugins (deflist, abbr, footnote, - sub, sup, ins, mark). - - Updated CM spec conformance to v0.15 (better unicode support). - - Added \`md\` (parser instance) link to all state objects (instead of former - options/parser). - - References/Footnotes/Abbrs moved to \`block\` chain. - - Input normalization moved to \`core\` chain. - - Splitted links and images to separate rules. - - Renamed some rules. - - Removed \`full\` preset. Not needed anymore. - - enable/disable methods now throw by default on invalid rules (exceptions can - be disabled). - - Replace NULL characters with 0xFFFD instead of strip. - - Removed custom fences sugar (overcomplication). - - Rewritten link components parse helpers. - - More functions in \`md.utils\`. - - ### Fixed - - Fixed inline html comments & cdata parse. - - - ## [2.2.1] - 2014-12-29 - ### Added - - Added development info. - - ### Changed - - .use() now pass any number of params to plugins. - - ### Fixed - - Fixed line breaks in definitions lists. - - - ## [2.2.0] - 2014-12-28 - ### Added - - API docs. - - Added 'zero' preset. - - ### Changed - - Updated CM spec conformance to v0.13. - - ### Fixed - - Fixed several crashes, when some basic rules are disabled - (block termination check, references check). - - - ## [2.1.3] - 2014-12-24 - ### Added - - Added curring to \`set\`/\`configure\`/\`enable\`/\`disable\` methods. - - ### Changed - - Demo rework - now can include plugins. - - Docs update. - - - ## [2.1.2] - 2014-12-23 - ### Changed - - Exposed helpers into parser instances (for plugins). - - Removed utils from global export - been in instances seems enougth. - - Refactored demo & added markdown-it-emoji to it. - - - ## [2.1.1] - 2014-12-22 - ### Changed - - Refreshed browser builds, missed in prev release. - - Minor changes. - - - ## [2.1.0] - 2014-12-21 - ### Changed - - Separated method to enable rules by whitelist (enableOnly). - - Changed second param of enable/disable ruler methods. - - Shortcuts in main class for bulk enable/disable rules. - - ASCII-friendly browserified files. - - Separate package for spec tests. - - - ## [2.0.0] - 2014-12-20 - ### Changed - - New project name & home! Now it's \`markdown-it\`, - - Sugar for constructor call - \`new\` is not mandatory now. - - Renamed presets folder (configs -> presets). - - - [12.2.0]: https://github.com/markdown-it/markdown-it/compare/12.1.0...12.2.0 - [12.1.0]: https://github.com/markdown-it/markdown-it/compare/12.0.6...12.1.0 - [12.0.6]: https://github.com/markdown-it/markdown-it/compare/12.0.5...12.0.6 - [12.0.5]: https://github.com/markdown-it/markdown-it/compare/12.0.4...12.0.5 - [12.0.4]: https://github.com/markdown-it/markdown-it/compare/12.0.3...12.0.4 - [12.0.3]: https://github.com/markdown-it/markdown-it/compare/12.0.2...12.0.3 - [12.0.2]: https://github.com/markdown-it/markdown-it/compare/12.0.1...12.0.2 - [12.0.1]: https://github.com/markdown-it/markdown-it/compare/12.0.0...12.0.1 - [12.0.0]: https://github.com/markdown-it/markdown-it/compare/11.0.1...12.0.0 - [11.0.1]: https://github.com/markdown-it/markdown-it/compare/11.0.0...11.0.1 - [11.0.0]: https://github.com/markdown-it/markdown-it/compare/10.0.0...11.0.0 - [10.0.0]: https://github.com/markdown-it/markdown-it/compare/9.1.0...10.0.0 - [9.1.0]: https://github.com/markdown-it/markdown-it/compare/9.0.1...9.1.0 - [9.0.1]: https://github.com/markdown-it/markdown-it/compare/9.0.0...9.0.1 - [9.0.0]: https://github.com/markdown-it/markdown-it/compare/8.4.2...9.0.0 - [8.4.2]: https://github.com/markdown-it/markdown-it/compare/8.4.1...8.4.2 - [8.4.1]: https://github.com/markdown-it/markdown-it/compare/8.4.0...8.4.1 - [8.4.0]: https://github.com/markdown-it/markdown-it/compare/8.3.2...8.4.0 - [8.3.2]: https://github.com/markdown-it/markdown-it/compare/8.3.1...8.3.2 - [8.3.1]: https://github.com/markdown-it/markdown-it/compare/8.3.0...8.3.1 - [8.3.0]: https://github.com/markdown-it/markdown-it/compare/8.2.2...8.3.0 - [8.2.2]: https://github.com/markdown-it/markdown-it/compare/8.2.1...8.2.2 - [8.2.1]: https://github.com/markdown-it/markdown-it/compare/8.2.0...8.2.1 - [8.2.0]: https://github.com/markdown-it/markdown-it/compare/8.1.0...8.2.0 - [8.1.0]: https://github.com/markdown-it/markdown-it/compare/8.0.1...8.1.0 - [8.0.1]: https://github.com/markdown-it/markdown-it/compare/8.0.0...8.0.1 - [8.0.0]: https://github.com/markdown-it/markdown-it/compare/7.0.1...8.0.0 - [7.0.1]: https://github.com/markdown-it/markdown-it/compare/7.0.0...7.0.1 - [7.0.0]: https://github.com/markdown-it/markdown-it/compare/6.1.1...7.0.0 - [6.1.1]: https://github.com/markdown-it/markdown-it/compare/6.1.0...6.1.1 - [6.1.0]: https://github.com/markdown-it/markdown-it/compare/6.0.5...6.1.0 - [6.0.5]: https://github.com/markdown-it/markdown-it/compare/6.0.4...6.0.5 - [6.0.4]: https://github.com/markdown-it/markdown-it/compare/6.0.3...6.0.4 - [6.0.3]: https://github.com/markdown-it/markdown-it/compare/6.0.2...6.0.3 - [6.0.2]: https://github.com/markdown-it/markdown-it/compare/6.0.1...6.0.2 - [6.0.1]: https://github.com/markdown-it/markdown-it/compare/6.0.0...6.0.1 - [6.0.0]: https://github.com/markdown-it/markdown-it/compare/5.1.0...6.0.0 - [5.1.0]: https://github.com/markdown-it/markdown-it/compare/5.0.3...5.1.0 - [5.0.3]: https://github.com/markdown-it/markdown-it/compare/5.0.2...5.0.3 - [5.0.2]: https://github.com/markdown-it/markdown-it/compare/5.0.1...5.0.2 - [5.0.1]: https://github.com/markdown-it/markdown-it/compare/5.0.0...5.0.1 - [5.0.0]: https://github.com/markdown-it/markdown-it/compare/4.4.0...5.0.0 - [4.4.0]: https://github.com/markdown-it/markdown-it/compare/4.3.1...4.4.0 - [4.3.1]: https://github.com/markdown-it/markdown-it/compare/4.3.0...4.3.1 - [4.3.0]: https://github.com/markdown-it/markdown-it/compare/4.2.2...4.3.0 - [4.2.2]: https://github.com/markdown-it/markdown-it/compare/4.2.1...4.2.2 - [4.2.1]: https://github.com/markdown-it/markdown-it/compare/4.2.0...4.2.1 - [4.2.0]: https://github.com/markdown-it/markdown-it/compare/4.1.2...4.2.0 - [4.1.2]: https://github.com/markdown-it/markdown-it/compare/4.1.1...4.1.2 - [4.1.1]: https://github.com/markdown-it/markdown-it/compare/4.1.0...4.1.1 - [4.1.0]: https://github.com/markdown-it/markdown-it/compare/4.0.3...4.1.0 - [4.0.3]: https://github.com/markdown-it/markdown-it/compare/4.0.2...4.0.3 - [4.0.2]: https://github.com/markdown-it/markdown-it/compare/4.0.1...4.0.2 - [4.0.1]: https://github.com/markdown-it/markdown-it/compare/4.0.0...4.0.1 - [4.0.0]: https://github.com/markdown-it/markdown-it/compare/3.1.0...4.0.0 - [3.1.0]: https://github.com/markdown-it/markdown-it/compare/3.0.7...3.1.0 - [3.0.7]: https://github.com/markdown-it/markdown-it/compare/3.0.6...3.0.7 - [3.0.6]: https://github.com/markdown-it/markdown-it/compare/3.0.5...3.0.6 - [3.0.5]: https://github.com/markdown-it/markdown-it/compare/3.0.4...3.0.5 - [3.0.4]: https://github.com/markdown-it/markdown-it/compare/3.0.3...3.0.4 - [3.0.3]: https://github.com/markdown-it/markdown-it/compare/3.0.2...3.0.3 - [3.0.2]: https://github.com/markdown-it/markdown-it/compare/3.0.1...3.0.2 - [3.0.1]: https://github.com/markdown-it/markdown-it/compare/3.0.0...3.0.1 - [3.0.0]: https://github.com/markdown-it/markdown-it/compare/2.2.1...3.0.0 - [2.2.1]: https://github.com/markdown-it/markdown-it/compare/2.2.0...2.2.1 - [2.2.0]: https://github.com/markdown-it/markdown-it/compare/2.1.3...2.2.0 - [2.1.3]: https://github.com/markdown-it/markdown-it/compare/2.1.2...2.1.3 - [2.1.2]: https://github.com/markdown-it/markdown-it/compare/2.1.1...2.1.2 - [2.1.1]: https://github.com/markdown-it/markdown-it/compare/2.1.0...2.1.1 - [2.1.0]: https://github.com/markdown-it/markdown-it/compare/2.0.0...2.1.0 - [2.0.0]: https://github.com/markdown-it/markdown-it/releases/tag/2.0.0`); +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## [12.2.0] - 2021-08-02 +### Added +- Ordered lists: add order value to token info. + +### Fixed +- Always suffix indented code block with a newline, #799. + + +## [12.1.0] - 2021-07-01 +### Changed +- Updated CM spec compatibility to 0.30. + + +## [12.0.6] - 2021-04-16 +### Fixed +- Newline in \`alt\` should be rendered, #775. + + +## [12.0.5] - 2021-04-15 +### Fixed +- HTML block tags with \`===\` inside are no longer incorrectly interpreted as headers, #772. +- Fix table/list parsing ambiguity, #767. + + +## [12.0.4] - 2020-12-20 +### Fixed +- Fix crash introduced in \`12.0.3\` when processing strikethrough (\`~~\`) and similar plugins, #742. +- Avoid fenced token mutation, #745. + + +## [12.0.3] - 2020-12-07 +### Fixed +- \`[]()\` is no longer a valid link. +- \`[](url (xxx())\` is no longer a valid link. +- \`[](url xxx)\` is no longer a valid link. +- Fix performance issues when parsing links (#732, #734), backticks, (#733, #736), + emphases (#735), and autolinks (#737). +- Allow newline in \`\` in an inline context. +- Allow \`\` html tag to appear in an inline context. + + +## [12.0.2] - 2020-10-23 +### Fixed +- Three pipes (\`|\n|\n|\`) are no longer rendered as a table with no columns, #724. + + +## [12.0.1] - 2020-10-19 +### Fixed +- Fix tables inside lists indented with tabs, #721. + + +## [12.0.0] - 2020-10-14 +### Added +- \`.gitattributes\`, force unix eol under windows, for development. + +### Changed +- Added 3rd argument to \`highlight(code, lang, attrs)\`, #626. +- Rewrite tables according to latest GFM spec, #697. +- Use \`rollup.js\` to browserify sources. +- Drop \`bower.json\` (bower reached EOL). +- Deps bump. +- Tune \`specsplit.js\` options. +- Drop \`Makefile\` in favour of npm scrips. + +### Fixed +- Fix mappings for table rows (amended fix made in 11.0.1), #705. +- \`%25\` is no longer decoded in beautified urls, #720. + +[12.2.0]: https://github.com/markdown-it/markdown-it/compare/12.1.0...12.2.0 +[12.1.0]: https://github.com/markdown-it/markdown-it/compare/12.0.6...12.1.0 +[12.0.6]: https://github.com/markdown-it/markdown-it/compare/12.0.5...12.0.6 +[12.0.5]: https://github.com/markdown-it/markdown-it/compare/12.0.4...12.0.5 +[12.0.4]: https://github.com/markdown-it/markdown-it/compare/12.0.3...12.0.4 +[12.0.3]: https://github.com/markdown-it/markdown-it/compare/12.0.2...12.0.3 +[12.0.2]: https://github.com/markdown-it/markdown-it/compare/12.0.1...12.0.2 +[12.0.1]: https://github.com/markdown-it/markdown-it/compare/12.0.0...12.0.1 +[12.0.0]: https://github.com/markdown-it/markdown-it/compare/11.0.1...12.0.0`); assert.equal(code.language, 'Markdown'); }); -test.skip('example 2', () => { +test('example 2', () => { const code = detectLang(`--- - draft: false - title: Why I use Linux instead of other OS - date: 2020-02-27 - desc: A post where I try to explain why I use this beautiful and awesome operating system called Linux - tags: - - linux - --- - - # Table of Content - - # Introduction - Hello internet people of the internet! In this post, I will explain the reason why I use Linux and how I know Linux. Well, the correct term here should be GNU/Linux but it's _way_ too long let's be honest. So, whenever I say Linux, what I mean is GNU/Linux. Let's start with how I know Linux. - - # Origin - ## My first laptop - It all started when I want to buy my first laptop. Roughly about 9 months ago. It runs Intel Celeron N4000 processor, which is pretty bad (yeah, I know). At that time, I didn't know about Thinkpad which most of people said has the best value for its price. So, I do some quick research on how ~~slow~~ fast this processor runs. It turns out, it's pretty bad. - - ## How I know Linux - I heard a lot of people say that Windows 10 is heavy for a slow processor like mine. It's bloat, it's too heavy, too many things going on, there's some malicious virus that can easily infect your computer, yaddi yadda. To be honest, I became a bit sad at that time. Then I came across a post on Facebook saying something like "Try Linux if your laptop/pc isn't powerful enough to run windows." Then I start to wonder, what is this guy talking about? Linux? I never heard that before. - - I became interested in that. Bare in mind that I don't have any laptop yet. I don't know why I love to read some articles about Linux and joined on several groups even if I don't have any machine that runs Linux (I even help people solve issues that they have on their Linux machine even though I don't have any laptop. That's quite something if you ask me). It's an interesting operating system (mainly because I never heard of it). Somehow, I like the fact that most people don't use it. I like to be different. Finally, after about a month, I bought my very first laptop. - - ## My first distribution - Linux has so many distributions. Like, a gazillion of them. But from what I observe, there are only a few "big boys" that stands out from the others. Some of them are Debian, Ubuntu, Arch, Manjaro, OpenSUSE, Fedora, RHEL, PopOS, etc. I got confused easily on which one is the best for me. Then I decided to check what's that guy is using on Facebook. - - The guy on Facebook runs [Manjaro Linux](https://manjaro.org). I was like, "Why did he choose that? That's a silly name for Linux." Not gonna lie, that's my first impression lol. About a week later, I tried to install one of Linux distribution after getting convinced enough. The one that I chose was [Linux Mint](https://linuxmint.com). At that time, I installed Linux Mint 19.1 XFCE Edition. I was so happy to be able to install Linux. Unfortunately, I lost my first screenshot on Linux Mint. - - ## Changing distribution - A month has passed. I feel pretty comfortable with Linux. Then, there was this news saying that Ubuntu dropped their support for 32bit libraries. Do you remember that news? I was like, "Well, that's fine I guess. What's wrong with that?" Little did I know, 32bit libraries are what most games depend on. Then I started to panic and confused lmao. - - I was like, "Oh come on. I'm already comfortable with my current setup. I still want to play some games but I don't want to change my distribution." Yep, that's literally what I said. And you know what? f*** it. Imma change my distribution. I decided to choose Manjaro since it's not based on Ubuntu. Yep, the one that I've mentioned before. A distribution that I thought has a stupid name (I felt so guilty now lol). Then I started to think, "Who cares about names anyway. As long as it is usable, it's good." - - Finally, I installed it. I took a quick screenshot after installing it because I was so excited. Here, take a look! - - ![manjaro](/assets/post/why-i-use-linux/manjaro.png) - - Manjaro is based on Arch. Some people say that it's Arch without all of its fuss. I mean, it's true. At the time I'm writing this, I use Arch. For beginners that want to try Archlinux, it's a good starting point. I ended up using it for nearly 8 months. It was a great experience. - - # Why Linux? - So, why do I use Linux then? Well, let me give you a quick list of why Linux is better than the other OS - - **It's free** - - Linux is free both in price and free as in freedom. You don't have to pay for license and you can do anyting you want with it. You can customize your Desktop Environment (look and feel) or even build your very own kernel! - - - **It's lightweight** - - Linux is so lightweight. It can bring your old hardware to life. There's this joke that says "Linux can run on everything". Starting from [business card](https://www.thirtythreeforty.net/posts/2019/12/my-business-card-runs-linux/) (yes, there's someone out there who built their business card with Linux inside it) until your high end $50000 beast or whatever. - - - **It's secure** - - Linux is very secure. That's why most of servers around the world is using Linux for it. You don't have to worry to install antivirus to prevent ransomware getting into your system. No need to worry on that stuff. - - - **There's always something to learn** - - Like, seriously. You can always learn something new everyday. There are so much good stuff that you can learn from Linux. If you like something challenging, go ahead and try Linux. - - - **Package Manager** - - Now this is the stuff that makes me really love Linux. Linux has a centralized place to download any app that you want. You don't need to go to some kind of obscure website and find the correct download link. You just need to \`apt install\` or \`pacman - S\` any package that you want and it's totally secure. - - # Conclusion - At first, I'm afraid that I can't install Windows on my new laptop. Who would've thought that in the end, I use Archlinux which some people say that it's difficult to install. I think it's not that hard, follow the wiki and you're set (said someone who had failed to install Archlinux 3 times lmao). - - Alright, this post will end right here. I might post why I use VIM/Window Managers next time. See ya in the next post everyone, have a good day!`); +draft: false +title: Why I use Linux instead of other OS +date: 2020-02-27 +desc: A post where I try to explain why I use this beautiful and awesome operating system called Linux +tags: + - linux +--- + +# Table of Content + +# Introduction +Hello internet people of the internet! In this post, I will explain the reason why I use Linux and how I know Linux. Well, the correct term here should be GNU/Linux but it's _way_ too long let's be honest. So, whenever I say Linux, what I mean is GNU/Linux. Let's start with how I know Linux. + +# Origin +## My first laptop +It all started when I want to buy my first laptop. Roughly about 9 months ago. It runs Intel Celeron N4000 processor, which is pretty bad (yeah, I know). At that time, I didn't know about Thinkpad which most of people said has the best value for its price. So, I do some quick research on how ~~slow~~ fast this processor runs. It turns out, it's pretty bad. + +## How I know Linux +I heard a lot of people say that Windows 10 is heavy for a slow processor like mine. It's bloat, it's too heavy, too many things going on, there's some malicious virus that can easily infect your computer, yaddi yadda. To be honest, I became a bit sad at that time. Then I came across a post on Facebook saying something like "Try Linux if your laptop/pc isn't powerful enough to run windows." Then I start to wonder, what is this guy talking about? Linux? I never heard that before. + +I became interested in that. Bare in mind that I don't have any laptop yet. I don't know why I love to read some articles about Linux and joined on several groups even if I don't have any machine that runs Linux (I even help people solve issues that they have on their Linux machine even though I don't have any laptop. That's quite something if you ask me). It's an interesting operating system (mainly because I never heard of it). Somehow, I like the fact that most people don't use it. I like to be different. Finally, after about a month, I bought my very first laptop. + +## My first distribution +Linux has so many distributions. Like, a gazillion of them. But from what I observe, there are only a few "big boys" that stands out from the others. Some of them are Debian, Ubuntu, Arch, Manjaro, OpenSUSE, Fedora, RHEL, PopOS, etc. I got confused easily on which one is the best for me. Then I decided to check what's that guy is using on Facebook. + +The guy on Facebook runs [Manjaro Linux](https://manjaro.org). I was like, "Why did he choose that? That's a silly name for Linux." Not gonna lie, that's my first impression lol. About a week later, I tried to install one of Linux distribution after getting convinced enough. The one that I chose was [Linux Mint](https://linuxmint.com). At that time, I installed Linux Mint 19.1 XFCE Edition. I was so happy to be able to install Linux. Unfortunately, I lost my first screenshot on Linux Mint. + +## Changing distribution +A month has passed. I feel pretty comfortable with Linux. Then, there was this news saying that Ubuntu dropped their support for 32bit libraries. Do you remember that news? I was like, "Well, that's fine I guess. What's wrong with that?" Little did I know, 32bit libraries are what most games depend on. Then I started to panic and confused lmao. + +I was like, "Oh come on. I'm already comfortable with my current setup. I still want to play some games but I don't want to change my distribution." Yep, that's literally what I said. And you know what? f*** it. Imma change my distribution. I decided to choose Manjaro since it's not based on Ubuntu. Yep, the one that I've mentioned before. A distribution that I thought has a stupid name (I felt so guilty now lol). Then I started to think, "Who cares about names anyway. As long as it is usable, it's good." + +Finally, I installed it. I took a quick screenshot after installing it because I was so excited. Here, take a look! + +![manjaro](/assets/post/why-i-use-linux/manjaro.png) + +Manjaro is based on Arch. Some people say that it's Arch without all of its fuss. I mean, it's true. At the time I'm writing this, I use Arch. For beginners that want to try Archlinux, it's a good starting point. I ended up using it for nearly 8 months. It was a great experience. + +# Why Linux? +So, why do I use Linux then? Well, let me give you a quick list of why Linux is better than the other OS + - **It's free** + + Linux is free both in price and free as in freedom. You don't have to pay for license and you can do anyting you want with it. You can customize your Desktop Environment (look and feel) or even build your very own kernel! + + - **It's lightweight** + + Linux is so lightweight. It can bring your old hardware to life. There's this joke that says "Linux can run on everything". Starting from [business card](https://www.thirtythreeforty.net/posts/2019/12/my-business-card-runs-linux/) (yes, there's someone out there who built their business card with Linux inside it) until your high end $50000 beast or whatever. + + - **It's secure** + + Linux is very secure. That's why most of servers around the world is using Linux for it. You don't have to worry to install antivirus to prevent ransomware getting into your system. No need to worry on that stuff. + + - **There's always something to learn** + + Like, seriously. You can always learn something new everyday. There are so much good stuff that you can learn from Linux. If you like something challenging, go ahead and try Linux. + + - **Package Manager** + + Now this is the stuff that makes me really love Linux. Linux has a centralized place to download any app that you want. You don't need to go to some kind of obscure website and find the correct download link. You just need to \`apt install\` or \`pacman - S\` any package that you want and it's totally secure. + +# Conclusion +At first, I'm afraid that I can't install Windows on my new laptop. Who would've thought that in the end, I use Archlinux which some people say that it's difficult to install. I think it's not that hard, follow the wiki and you're set (said someone who had failed to install Archlinux 3 times lmao). + +Alright, this post will end right here. I might post why I use VIM/Window Managers next time. See ya in the next post everyone, have a good day!`); assert.equal(code.language, 'Markdown'); }); -test.skip('example 3', () => { +test('example 3', () => { const code = detectLang(`--- - name: 'blog-using-vue-nuxt-markdown' - title: Website with blog and portfolio using Vue.js + Nuxt + Markdown - year: 1 January 2019 - color: '#8e7964' - trans: 'blog-usando-vue-nuxt-markdown' - id: 'vue-nuxt-blog' - description: | - How I created my new website with portfolio and blog in two languages. What technology I used and why. - --- - - ## Why did I re-do my website with Nuxt? - - Although some of you already know me, I am [Marina Aísa](https://twitter.com/MarinaAisa), UX Engineer (design and front-end) and I currently work at [Holaluz](https://www.holaluz.com/en). - - Last year, 2018, I was very focused on learning more about JavaScript, which was a pending subject and at the same time I learnt [Vue.js](https://vuejs.org/). Meanwhile at my workplace, we started using [Nuxt.js](https://nuxtjs.org/) a framework on VueJS to remake both company's static and dynamic (SPA) webapps into components and create a design system with it. - - My previous website was made with [Middleman](https://middlemanapp.com/) a static pages generator based on Ruby, so I took the opportunity to redo my website with Nuxt and Vue, in order to: - - To learn - - Improve performance - - Add functionality as a blog and portfolio system - - Add two languages, Spanish and English, **also in blog posts** but independently, since I guess I won't translate every post in both languages. - - What attracts me the most of Nuxt is the philosophy *serverless* (Nuxt can also be SSR tho) and the static prerendering it provides to SPA applications. Briefly, with this stack you can combine the best of a static website: compiled HTML -> what leads to a better SEO, plus the best of a *single page application*: Webpack, cache optimizations, lazy-loading, functions and asynchronous data... - - ## But where do I get the content if I don't have a server? - - Nuxt, by following the architecture [JAMStack](https://jamstack.org/) is built to get content through APIs, so many people use headless CMSs like [Contentful](https://www.contentful.com/) or [Prismic](https://prismic.io/). At first I thought they were interesting options but I realized that it wasn't necessary for a website like mine since CMSs are oriented to be used by people without technical knowledge, besides they are expensive, they save assets on their own servers and they aren't the best option if I wanted to have the best performance. - - **Therefore, I decided to use a Markdowns system that I store in Github and call dynamically.** - - ### Importing posts on the main page depending on the language - - Using the asynchronous function \`asyncData\` that Nuxt provides only in its pages (it is not avalaible in its components) I import the Markdowns that I have saved in the folder \`content\` of the project. Later I return them in the form of a promise as an array of objects. As you can see below, this import depends on the constant \`blogs\` which will be the array \`blogsEs\` or \`blogsEn\` depending on the language of the page stored on the Vuex's state. - - \`\`\`javascript - import blogsEn from '~/contents/en/blogsEn.js'; - import blogsEs from '~/contents/es/blogsEs.js' - - async asyncData({ app }) { - const blogs = app.i18n.locale === 'en' ? blogsEn : blogsEs; - - async function asyncImport(blogName) { - const wholeMD = await import(\`~/content/\${app.i18n.locale}/blog/\${blogName}.md\`); - return wholeMD.attributes; - } - - return Promise.all(blogs.map(blog => asyncImport(blog))) - .then((res) => { - return { - blogs: res - }; - }); - } - \`\`\` - - The reason why I'm importing the arrays containing the blogs names is because I want to use it also to generate the static pages through the object [generate](https://nuxtjs.org/api/configuration-generate/) in the Nuxt configuration, file \`nuxt.config.js\`. - - \`\`\`javascript; - import blogsEn from '~/contents/en/blogsEn.js'; - import blogsEs from '~/contents/es/blogsEs.js'; - - generate: { - routes: [ - '/es', '404' - ] - .concat(blogsEn.map(blog => \`/blog/\${blog}\`)) - .concat(blogsEs.map(blog => \`es/blog/\${blog}\`)); - } - \`\`\` - - ### Generating dynamic pages from Markdown files - - Nuxt has a very interesting functionality, the creation of [dynamic routes](https://nuxtjs.org/guide/routing/#dynamic-routes). - - In the next import I use the function \`asyncData\` instead of \`data\` as it's usual in Vue, to first import each Markdown and then return a new object with the information I want to use in the template of the page. - **The URL will be equal to each markdown file's name.** - In the case that the md file doesn't exist it will simply go to error page 404. - - \`\`\`javascript - async asyncData({ params, app }) { - const fileContent = await import(\`~/contents/\${app.i18n.locale}/blog/\${params.slug}.md\`); - const attr = fileContent.attributes; - return { - colors: attr.colors, - date: attr.date, - description: attr.description, - id: attr.id, - name: params.slug, - related: attr.related, - renderFunc: fileContent.vue.render, - staticRenderFuncs: fileContent.vue.staticRenderFns, - title: attr.title, - urlTranslation: attr.urlTranslation - }; +name: 'blog-using-vue-nuxt-markdown' +title: Website with blog and portfolio using Vue.js + Nuxt + Markdown +year: 1 January 2019 +color: '#8e7964' +trans: 'blog-usando-vue-nuxt-markdown' +id: 'vue-nuxt-blog' +description: | + How I created my new website with portfolio and blog in two languages. What technology I used and why. +--- + +## Why did I re-do my website with Nuxt? + +Although some of you already know me, I am [Marina Aísa](https://twitter.com/MarinaAisa), UX Engineer (design and front-end) and I currently work at [Holaluz](https://www.holaluz.com/en). + +Last year, 2018, I was very focused on learning more about JavaScript, which was a pending subject and at the same time I learnt [Vue.js](https://vuejs.org/). Meanwhile at my workplace, we started using [Nuxt.js](https://nuxtjs.org/) a framework on VueJS to remake both company's static and dynamic (SPA) webapps into components and create a design system with it. + +My previous website was made with [Middleman](https://middlemanapp.com/) a static pages generator based on Ruby, so I took the opportunity to redo my website with Nuxt and Vue, in order to: +- To learn +- Improve performance +- Add functionality as a blog and portfolio system +- Add two languages, Spanish and English, **also in blog posts** but independently, since I guess I won't translate every post in both languages. + +What attracts me the most of Nuxt is the philosophy *serverless* (Nuxt can also be SSR tho) and the static prerendering it provides to SPA applications. Briefly, with this stack you can combine the best of a static website: compiled HTML -> what leads to a better SEO, plus the best of a *single page application*: Webpack, cache optimizations, lazy-loading, functions and asynchronous data... + +## But where do I get the content if I don't have a server? + +Nuxt, by following the architecture [JAMStack](https://jamstack.org/) is built to get content through APIs, so many people use headless CMSs like [Contentful](https://www.contentful.com/) or [Prismic](https://prismic.io/). At first I thought they were interesting options but I realized that it wasn't necessary for a website like mine since CMSs are oriented to be used by people without technical knowledge, besides they are expensive, they save assets on their own servers and they aren't the best option if I wanted to have the best performance. + +**Therefore, I decided to use a Markdowns system that I store in Github and call dynamically.** + +### Importing posts on the main page depending on the language + +Using the asynchronous function \`asyncData\` that Nuxt provides only in its pages (it is not avalaible in its components) I import the Markdowns that I have saved in the folder \`content\` of the project. Later I return them in the form of a promise as an array of objects. As you can see below, this import depends on the constant \`blogs\` which will be the array \`blogsEs\` or \`blogsEn\` depending on the language of the page stored on the Vuex's state. + +\`\`\`javascript +import blogsEn from '~/contents/en/blogsEn.js'; +import blogsEs from '~/contents/es/blogsEs.js' + +async asyncData({ app }) { + const blogs = app.i18n.locale === 'en' ? blogsEn : blogsEs; + + async function asyncImport(blogName) { + const wholeMD = await import(\`~/content/\${app.i18n.locale}/blog/\${blogName}.md\`); + return wholeMD.attributes; } - \`\`\` - - If we wanted to create a portfolio in the future, it would be exactly the same as the blog. We would create within \`contents\` a folder called \`portfolio\` and we would do the same process that we have done with \`blogs\`. - - The loader for Webpack Markdown files that I use is: [frontmatter-markdown-loader](https://www.npmjs.com/package/frontmatter-markdown-loader) that allows me to put Vue components inside markdown files, as well as extract the \`frontmatter\` attributes as they do static generators like Jekyll. For making the code look pretty I apply: [HighlightJS](https://highlightjs.org/) - - ## Let's talk about performance - - Do you remember that before I told you that one of my motivations for creating this website was to have a blog that had a good performance? - With Nuxt I have achieved it, and I still have a lot to optimize. - - If you have arrived here, you have probably thought: *"OMG Marina, you could just have made a blog in [Medium](https://medium.com/) and save you all this crazy work"* and right now you're going to understand why I don't like Medium. - - While writing in Medium **you don't have control over your blog** such as CSS, SEO, adding functionalities, **Medium owns your content**, you have a limit of articles read for free... and **their performance seems quite bad** - - Thanks to Google's tool [Lighthouse](https://developers.google.com/web/fundamentals/performance/audit/) we can analyze and compare Medium with my website. - - - - As you can see, Medium does a lot of things well, but performance is not one of them. This translates into user experience as a very slow load, especially on mobile devices. **Because performance is user experience.** We'll talk more about it another day. - The interesting thing here is that with Nuxt I managed to reach a **94%** performance compared to 40% offered by Medium in the first load, but the best thing is that since using cache systems, **the second load on my website the performance is 100%** while Medium scores 60%. - - ## Web in two languages - - To translate the web in English and Spanish I use [nuxt-i18n](https://github.com/nuxt-community/nuxt-i18n). It is a layer above [vue-i18n](https://github.com/kazupon/vue-i18n) which has lazy-loading translations. *Nuxt-i18n* automates how translations are worked on the Vue router, simplifying it for Nuxt. I recommend it for the router, although it has some things that I couldn't managed to make it work as the redirection cookie based on the browser language. But it's a problem that you have to accept if you use a new framework like Nuxt is. - - ## Features and improvements I want to add in the future - - - I am not very happy with the amount of JS that I am putting into the web, I have more than 100k of synchronous JS and I want to reduce it. I still have to figure out how. My relationship with JS is love/hate. On the one hand I love everything you can do with it and on the other I hate it because it has a terrible cost on the performance of the page. - - - Adding a portfolio system with dynamic pages like the blog. - - - Improvements in design and usability. - - - Making the web totally accessible from the design to the code. - - - Cleaning CSS that I don't use and try to reduce it. - - - I criticize a lot Medium but I really like its design and some of its features, in fact I would like to add its famous *clap* button to my website. - - - Add comments to each post. - - - Add similar posts to the one you've read. - - ## Things about the webapp that I'll write another day - - - Lazy loading of components and images in Nuxt, I will tell you which packages I use and the component I did to render a first image as a *placeholder* in base64 and afterwards asynchronously the final image. - - - How to use \`analyze\` of Nuxt to analyze the JS generated by Webpack in our app and to optimize it. - - - The big mistake I made along the way: Vuex. You can read it here - - - How to put emojis on your website through a sprite made in SCSS so that they always look the same regardless of the browser or device. - - - Loading Vue asynchronous components with the practical example of the travel map that is in the home page. - - I thought about publishing a starter about it but being realist, I wouldn't have enough time to maintain it. I think this post explains how to do it very well, but if you have any doubt left, you can always contact me at my email: [marina@marinaaisa](mailto:marina@marinaaisa.com). - - Since I don't have a comments section on each post, I would love to continue the conversation on [Twitter](https://twitter.com/MarinaAisa). All feedback is welcome! If you think there is something that it can be improved, you would help me a lot.`); + + return Promise.all(blogs.map(blog => asyncImport(blog))) + .then((res) => { + return { + blogs: res + }; + }); +} +\`\`\` + +The reason why I'm importing the arrays containing the blogs names is because I want to use it also to generate the static pages through the object [generate](https://nuxtjs.org/api/configuration-generate/) in the Nuxt configuration, file \`nuxt.config.js\`. + +\`\`\`javascript; +import blogsEn from '~/contents/en/blogsEn.js'; +import blogsEs from '~/contents/es/blogsEs.js'; + +generate: { + routes: [ + '/es', '404' + ] + .concat(blogsEn.map(blog => \`/blog/\${blog}\`)) + .concat(blogsEs.map(blog => \`es/blog/\${blog}\`)); +} +\`\`\` + +### Generating dynamic pages from Markdown files + +Nuxt has a very interesting functionality, the creation of [dynamic routes](https://nuxtjs.org/guide/routing/#dynamic-routes). + +In the next import I use the function \`asyncData\` instead of \`data\` as it's usual in Vue, to first import each Markdown and then return a new object with the information I want to use in the template of the page. +**The URL will be equal to each markdown file's name.** +In the case that the md file doesn't exist it will simply go to error page 404. + +\`\`\`javascript +async asyncData({ params, app }) { + const fileContent = await import(\`~/contents/\${app.i18n.locale}/blog/\${params.slug}.md\`); + const attr = fileContent.attributes; + return { + colors: attr.colors, + date: attr.date, + description: attr.description, + id: attr.id, + name: params.slug, + related: attr.related, + renderFunc: fileContent.vue.render, + staticRenderFuncs: fileContent.vue.staticRenderFns, + title: attr.title, + urlTranslation: attr.urlTranslation + }; +} +\`\`\` + +If we wanted to create a portfolio in the future, it would be exactly the same as the blog. We would create within \`contents\` a folder called \`portfolio\` and we would do the same process that we have done with \`blogs\`. + +The loader for Webpack Markdown files that I use is: [frontmatter-markdown-loader](https://www.npmjs.com/package/frontmatter-markdown-loader) that allows me to put Vue components inside markdown files, as well as extract the \`frontmatter\` attributes as they do static generators like Jekyll. For making the code look pretty I apply: [HighlightJS](https://highlightjs.org/) + +## Let's talk about performance + +Do you remember that before I told you that one of my motivations for creating this website was to have a blog that had a good performance? +With Nuxt I have achieved it, and I still have a lot to optimize. + +If you have arrived here, you have probably thought: *"OMG Marina, you could just have made a blog in [Medium](https://medium.com/) and save you all this crazy work"* and right now you're going to understand why I don't like Medium. + +While writing in Medium **you don't have control over your blog** such as CSS, SEO, adding functionalities, **Medium owns your content**, you have a limit of articles read for free... and **their performance seems quite bad** + +Thanks to Google's tool [Lighthouse](https://developers.google.com/web/fundamentals/performance/audit/) we can analyze and compare Medium with my website. + + + +As you can see, Medium does a lot of things well, but performance is not one of them. This translates into user experience as a very slow load, especially on mobile devices. **Because performance is user experience.** We'll talk more about it another day. +The interesting thing here is that with Nuxt I managed to reach a **94%** performance compared to 40% offered by Medium in the first load, but the best thing is that since using cache systems, **the second load on my website the performance is 100%** while Medium scores 60%. + +## Web in two languages + +To translate the web in English and Spanish I use [nuxt-i18n](https://github.com/nuxt-community/nuxt-i18n). It is a layer above [vue-i18n](https://github.com/kazupon/vue-i18n) which has lazy-loading translations. *Nuxt-i18n* automates how translations are worked on the Vue router, simplifying it for Nuxt. I recommend it for the router, although it has some things that I couldn't managed to make it work as the redirection cookie based on the browser language. But it's a problem that you have to accept if you use a new framework like Nuxt is. + +## Features and improvements I want to add in the future + +- I am not very happy with the amount of JS that I am putting into the web, I have more than 100k of synchronous JS and I want to reduce it. I still have to figure out how. My relationship with JS is love/hate. On the one hand I love everything you can do with it and on the other I hate it because it has a terrible cost on the performance of the page. + +- Adding a portfolio system with dynamic pages like the blog. + +- Improvements in design and usability. + +- Making the web totally accessible from the design to the code. + +- Cleaning CSS that I don't use and try to reduce it. + +- I criticize a lot Medium but I really like its design and some of its features, in fact I would like to add its famous *clap* button to my website. + +- Add comments to each post. + +- Add similar posts to the one you've read. + +## Things about the webapp that I'll write another day + +- Lazy loading of components and images in Nuxt, I will tell you which packages I use and the component I did to render a first image as a *placeholder* in base64 and afterwards asynchronously the final image. + +- How to use \`analyze\` of Nuxt to analyze the JS generated by Webpack in our app and to optimize it. + +- The big mistake I made along the way: Vuex. You can read it here + +- How to put emojis on your website through a sprite made in SCSS so that they always look the same regardless of the browser or device. + +- Loading Vue asynchronous components with the practical example of the travel map that is in the home page. + +I thought about publishing a starter about it but being realist, I wouldn't have enough time to maintain it. I think this post explains how to do it very well, but if you have any doubt left, you can always contact me at my email: [marina@marinaaisa](mailto:marina@marinaaisa.com). + +Since I don't have a comments section on each post, I would love to continue the conversation on [Twitter](https://twitter.com/MarinaAisa). All feedback is welcome! If you think there is something that it can be improved, you would help me a lot.`); + assert.equal(code.language, 'Markdown'); +}); + +test('example 4', () => { + const code = detectLang(`# Visual Studio Code - Open Source ("Code - OSS") +[![Feature Requests](https://img.shields.io/github/issues/microsoft/vscode/feature-request.svg)](https://github.com/microsoft/vscode/issues?q=is%3Aopen+is%3Aissue+label%3Afeature-request+sort%3Areactions-%2B1-desc) +[![Bugs](https://img.shields.io/github/issues/microsoft/vscode/bug.svg)](https://github.com/microsoft/vscode/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Abug) +[![Gitter](https://img.shields.io/badge/chat-on%20gitter-yellow.svg)](https://gitter.im/Microsoft/vscode) + +## The Repository + +This repository ("\`Code - OSS\`") is where we (Microsoft) develop the [Visual Studio Code](https://code.visualstudio.com) product together with the community. Not only do we work on code and issues here, we also publish our [roadmap](https://github.com/microsoft/vscode/wiki/Roadmap), [monthly iteration plans](https://github.com/microsoft/vscode/wiki/Iteration-Plans), and our [endgame plans](https://github.com/microsoft/vscode/wiki/Running-the-Endgame). This source code is available to everyone under the standard [MIT license](https://github.com/microsoft/vscode/blob/main/LICENSE.txt). + +## Visual Studio Code + +

+ VS Code in action +

+ +[Visual Studio Code](https://code.visualstudio.com) is a distribution of the \`Code - OSS\` repository with Microsoft specific customizations released under a traditional [Microsoft product license](https://code.visualstudio.com/License/). + +[Visual Studio Code](https://code.visualstudio.com) combines the simplicity of a code editor with what developers need for their core edit-build-debug cycle. It provides comprehensive code editing, navigation, and understanding support along with lightweight debugging, a rich extensibility model, and lightweight integration with existing tools. + +Visual Studio Code is updated monthly with new features and bug fixes. You can download it for Windows, macOS, and Linux on [Visual Studio Code's website](https://code.visualstudio.com/Download). To get the latest releases every day, install the [Insiders build](https://code.visualstudio.com/insiders). + +## Contributing + +There are many ways in which you can participate in this project, for example: + +* [Submit bugs and feature requests](https://github.com/microsoft/vscode/issues), and help us verify as they are checked in +* Review [source code changes](https://github.com/microsoft/vscode/pulls) +* Review the [documentation](https://github.com/microsoft/vscode-docs) and make pull requests for anything from typos to additional and new content + +If you are interested in fixing issues and contributing directly to the code base, +please see the document [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute), which covers the following: + +* [How to build and run from source](https://github.com/microsoft/vscode/wiki/How-to-Contribute) +* [The development workflow, including debugging and running tests](https://github.com/microsoft/vscode/wiki/How-to-Contribute#debugging) +* [Coding guidelines](https://github.com/microsoft/vscode/wiki/Coding-Guidelines) +* [Submitting pull requests](https://github.com/microsoft/vscode/wiki/How-to-Contribute#pull-requests) +* [Finding an issue to work on](https://github.com/microsoft/vscode/wiki/How-to-Contribute#where-to-contribute) +* [Contributing to translations](https://aka.ms/vscodeloc) + +## Feedback + +* Ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/vscode) +* [Request a new feature](CONTRIBUTING.md) +* Upvote [popular feature requests](https://github.com/microsoft/vscode/issues?q=is%3Aopen+is%3Aissue+label%3Afeature-request+sort%3Areactions-%2B1-desc) +* [File an issue](https://github.com/microsoft/vscode/issues) +* Follow [@code](https://twitter.com/code) and let us know what you think! + +See our [wiki](https://github.com/microsoft/vscode/wiki/Feedback-Channels) for a description of each of these channels and information on some other available community-driven channels. + +## Related Projects + +Many of the core components and extensions to VS Code live in their own repositories on GitHub. For example, the [node debug adapter](https://github.com/microsoft/vscode-node-debug) and the [mono debug adapter](https://github.com/microsoft/vscode-mono-debug) have their own repositories. For a complete list, please visit the [Related Projects](https://github.com/microsoft/vscode/wiki/Related-Projects) page on our [wiki](https://github.com/microsoft/vscode/wiki). + +## Bundled Extensions + +VS Code includes a set of built-in extensions located in the [extensions](extensions) folder, including grammars and snippets for many languages. Extensions that provide rich language support (code completion, Go to Definition) for a language have the suffix \`language-features\`. For example, the \`json\` extension provides coloring for \`JSON\` and the \`json-language-features\` provides rich language support for \`JSON\`. + +## Development Container + +This repository includes a Visual Studio Code Remote - Containers / GitHub Codespaces development container. + +- For [Remote - Containers](https://aka.ms/vscode-remote/download/containers), use the **Remote-Containers: Clone Repository in Container Volume...** command which creates a Docker volume for better disk I/O on macOS and Windows. +- For Codespaces, install the [Github Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) extension in VS Code, and use the **Codespaces: Create New Codespace** command. + +Docker / the Codespace should have at least **4 Cores and 6 GB of RAM (8 GB recommended)** to run full build. See the [development container README](.devcontainer/README.md) for more information. + +## Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +## License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Licensed under the [MIT](LICENSE.txt) license.`); assert.equal(code.language, 'Markdown'); });