From ad2b987a553550a59380f5e05d2021e3fe90b08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20D=C3=A9ramond?= Date: Wed, 25 Sep 2024 18:33:18 +0200 Subject: [PATCH] feat: add `markdown` and `markdown/table` --- .../__snapshots__/customFormats.test.snap.js | 8 + .../__snapshots__/markdown.test.snap.js | 349 ++++++++++++++++++ __integration__/markdown.test.js | 70 ++++ .../formats/__snapshots__/all.test.snap.js | 25 ++ .../docs/reference/Hooks/Formats/index.md | 1 + .../reference/Hooks/Formats/predefined.md | 21 ++ .../Hooks/Transform Groups/predefined.md | 9 + lib/common/formats.js | 45 +++ .../templates/markdown/table.md.template.js | 30 ++ lib/common/transformGroups.js | 10 + 10 files changed, 568 insertions(+) create mode 100644 __integration__/__snapshots__/markdown.test.snap.js create mode 100644 __integration__/markdown.test.js create mode 100644 lib/common/templates/markdown/table.md.template.js diff --git a/__integration__/__snapshots__/customFormats.test.snap.js b/__integration__/__snapshots__/customFormats.test.snap.js index d2ca28e1c..edd137a06 100644 --- a/__integration__/__snapshots__/customFormats.test.snap.js +++ b/__integration__/__snapshots__/customFormats.test.snap.js @@ -717,6 +717,10 @@ snapshots["integration custom formats inline custom with new args should match s "name/camel", "color/css", "size/object" + ], + "markdown": [ + "attribute/cti", + "name/human" ] }, "transforms": { @@ -1671,6 +1675,10 @@ snapshots["integration custom formats register custom format with new args shoul "name/camel", "color/css", "size/object" + ], + "markdown": [ + "attribute/cti", + "name/human" ] }, "transforms": { diff --git a/__integration__/__snapshots__/markdown.test.snap.js b/__integration__/__snapshots__/markdown.test.snap.js new file mode 100644 index 000000000..f73e616ce --- /dev/null +++ b/__integration__/__snapshots__/markdown.test.snap.js @@ -0,0 +1,349 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["integration markdown markdown/table should match snapshot"] = +` + + +| Token | Type | Value | +| --- | --- | --- | +| aqua 0 | color | \u0060#d9fcfb\u0060 | +| aqua 100 | color | \u0060#c5f9f9\u0060 | +| aqua 1000 | color | \u0060#083d4f\u0060 | +| aqua 1100 | color | \u0060#002838\u0060 | +| aqua 200 | color | \u0060#a5f2f2\u0060 | +| aqua 300 | color | \u0060#76e5e2\u0060 | +| aqua 400 | color | \u0060#33d6e2\u0060 | +| aqua 500 | color | \u0060#17b8ce\u0060 | +| aqua 600 | color | \u0060#0797ae\u0060 | +| aqua 700 | color | \u0060#0b8599\u0060 | +| aqua 800 | color | \u0060#0f6e84\u0060 | +| aqua 900 | color | \u0060#035e73\u0060 | +| blue 0 | color | \u0060#e9f8ff\u0060 | +| blue 100 | color | \u0060#dcf2ff\u0060 | +| blue 1000 | color | \u0060#0a3960\u0060 | +| blue 1100 | color | \u0060#002138\u0060 | +| blue 200 | color | \u0060#c7e4f9\u0060 | +| blue 300 | color | \u0060#a1d2f8\u0060 | +| blue 400 | color | \u0060#56adf5\u0060 | +| blue 500 | color | \u0060#3896e3\u0060 | +| blue 600 | color | \u0060#2b87d3\u0060 | +| blue 700 | color | \u0060#2079c3\u0060 | +| blue 800 | color | \u0060#116daa\u0060 | +| blue 900 | color | \u0060#0c5689\u0060 | +| danger | color | \u0060{color.core.red.0.value}\u0060 | +| danger | color | \u0060{color.core.red.1000.value}\u0060 | +| disabled | color | \u0060{color.background.tertiary.value}\u0060 | +| green 0 | color | \u0060#ebf9eb\u0060 | +| green 100 | color | \u0060#d7f4d7\u0060 | +| green 1000 | color | \u0060#08422f\u0060 | +| green 1100 | color | \u0060#002b20\u0060 | +| green 200 | color | \u0060#c2f2bd\u0060 | +| green 300 | color | \u0060#98e58e\u0060 | +| green 400 | color | \u0060#75dd66\u0060 | +| green 500 | color | \u0060#59cb59\u0060 | +| green 600 | color | \u0060#2bb656\u0060 | +| green 700 | color | \u0060#0ca750\u0060 | +| green 800 | color | \u0060#008b46\u0060 | +| green 900 | color | \u0060#006b40\u0060 | +| info | color | \u0060{color.core.blue.0.value}\u0060 | +| interactive _ | color | \u0060{color.brand.primary.value}\u0060 | +| interactive active | color | \u0060{color.brand.secondary.value}\u0060 | +| interactive disabled | color | \u0060{color.font.tertiary.value}\u0060 | +| interactive hover | color | \u0060{color.brand.primary.value}\u0060 | +| large | fontSize | \u00601.5\u0060 | +| large | dimension | \u00601\u0060 | +| magenta 0 | color | \u0060#fef0ff\u0060 | +| magenta 100 | color | \u0060#f9e3fc\u0060 | +| magenta 1000 | color | \u0060#451551\u0060 | +| magenta 1100 | color | \u0060#29192d\u0060 | +| magenta 200 | color | \u0060#f4c4f7\u0060 | +| magenta 300 | color | \u0060#edadf2\u0060 | +| magenta 400 | color | \u0060#f282f5\u0060 | +| magenta 500 | color | \u0060#db61db\u0060 | +| magenta 600 | color | \u0060#c44eb9\u0060 | +| magenta 700 | color | \u0060#ac44a8\u0060 | +| magenta 800 | color | \u0060#8f3896\u0060 | +| magenta 900 | color | \u0060#6c2277\u0060 | +| medium | fontSize | \u00601\u0060 | +| medium | dimension | \u00601\u0060 | +| neutral 0 | color | \u0060#FFFFFF\u0060 | +| neutral 100 | color | \u0060#f3f4f4\u0060 | +| neutral 1000 | color | \u0060#162020\u0060 | +| neutral 1100 | color | \u0060#040404\u0060 | +| neutral 200 | color | \u0060#dee1e1\u0060 | +| neutral 300 | color | \u0060#c8cccc\u0060 | +| neutral 400 | color | \u0060#b0b6b7\u0060 | +| neutral 500 | color | \u0060#929a9b\u0060 | +| neutral 600 | color | \u0060#6e797a\u0060 | +| neutral 700 | color | \u0060#515e5f\u0060 | +| neutral 800 | color | \u0060#364141\u0060 | +| neutral 900 | color | \u0060#273333\u0060 | +| orange 0 | color | \u0060#ffede3\u0060 | +| orange 100 | color | \u0060#fcdccc\u0060 | +| orange 1000 | color | \u0060#601700\u0060 | +| orange 1100 | color | \u0060#2d130e\u0060 | +| orange 200 | color | \u0060#ffc6a4\u0060 | +| orange 300 | color | \u0060#ffb180\u0060 | +| orange 400 | color | \u0060#ff9c5d\u0060 | +| orange 500 | color | \u0060#fc8943\u0060 | +| orange 600 | color | \u0060#f57d33\u0060 | +| orange 700 | color | \u0060#ed7024\u0060 | +| orange 800 | color | \u0060#ce5511\u0060 | +| orange 900 | color | \u0060#962c0b\u0060 | +| pink 0 | color | \u0060#ffe9f3\u0060 | +| pink 100 | color | \u0060#fcdbeb\u0060 | +| pink 1000 | color | \u0060#561231\u0060 | +| pink 1100 | color | \u0060#2b1721\u0060 | +| pink 200 | color | \u0060#ffb5d5\u0060 | +| pink 300 | color | \u0060#ff95c1\u0060 | +| pink 400 | color | \u0060#ff76ae\u0060 | +| pink 500 | color | \u0060#ef588b\u0060 | +| pink 600 | color | \u0060#e0447c\u0060 | +| pink 700 | color | \u0060#ce3665\u0060 | +| pink 800 | color | \u0060#b22f5b\u0060 | +| pink 900 | color | \u0060#931847\u0060 | +| primary | color | \u0060{color.core.neutral.0.value}\u0060 | +| primary | color | \u0060{color.core.neutral.300.value}\u0060 | +| primary | color | \u0060{color.core.aqua.700.value}\u0060 | +| primary | color | \u0060{color.core.neutral.1100.value}\u0060 | +| purple 0 | color | \u0060#f2f2f9\u0060 | +| purple 100 | color | \u0060#eaeaf9\u0060 | +| purple 1000 | color | \u0060#2d246b\u0060 | +| purple 1100 | color | \u0060#1d1d38\u0060 | +| purple 200 | color | \u0060#d8d7f9\u0060 | +| purple 300 | color | \u0060#c1c1f7\u0060 | +| purple 400 | color | \u0060#a193f2\u0060 | +| purple 500 | color | \u0060#9180f4\u0060 | +| purple 600 | color | \u0060#816fea\u0060 | +| purple 700 | color | \u0060#6f5ed3\u0060 | +| purple 800 | color | \u0060#5e4eba\u0060 | +| purple 900 | color | \u0060#483a9c\u0060 | +| radius large | dimension | \u006030\u0060 | +| red 0 | color | \u0060#ffeae9\u0060 | +| red 100 | color | \u0060#ffd5d2\u0060 | +| red 1000 | color | \u0060#6d1313\u0060 | +| red 1100 | color | \u0060#2b1111\u0060 | +| red 200 | color | \u0060#ffb8b1\u0060 | +| red 300 | color | \u0060#ff9c8f\u0060 | +| red 400 | color | \u0060#ff7f6e\u0060 | +| red 500 | color | \u0060#f76054\u0060 | +| red 600 | color | \u0060#ed4c42\u0060 | +| red 700 | color | \u0060#db3e3e\u0060 | +| red 800 | color | \u0060#c63434\u0060 | +| red 900 | color | \u0060#992222\u0060 | +| secondary | color | \u0060{color.core.neutral.100.value}\u0060 | +| secondary | color | \u0060{color.core.purple.700.value}\u0060 | +| secondary | color | \u0060{color.core.neutral.900.value}\u0060 | +| small | fontSize | \u00600.75\u0060 | +| small | dimension | \u00600.5\u0060 | +| success | color | \u0060{color.core.green.0.value}\u0060 | +| success | color | \u0060{color.core.green.1000}\u0060 | +| teal 0 | color | \u0060#e5f9f5\u0060 | +| teal 100 | color | \u0060#cdf7ef\u0060 | +| teal 1000 | color | \u0060#083f3f\u0060 | +| teal 1100 | color | \u0060#002528\u0060 | +| teal 200 | color | \u0060#b3f2e6\u0060 | +| teal 300 | color | \u0060#7dead5\u0060 | +| teal 400 | color | \u0060#24e0c5\u0060 | +| teal 500 | color | \u0060#08c4b2\u0060 | +| teal 600 | color | \u0060#00a99c\u0060 | +| teal 700 | color | \u0060#0b968f\u0060 | +| teal 800 | color | \u0060#067c7c\u0060 | +| teal 900 | color | \u0060#026661\u0060 | +| tertiary | color | \u0060{color.core.neutral.200.value}\u0060 | +| tertiary | color | \u0060{color.core.neutral.800.value}\u0060 | +| warning | color | \u0060{color.core.orange.0.value}\u0060 | +| warning | color | \u0060{color.core.orange.1000.value}\u0060 | +| xl | fontSize | \u00602.25\u0060 | +| xl | dimension | \u00601\u0060 | +| yellow 0 | color | \u0060#fff8e2\u0060 | +| yellow 100 | color | \u0060#fdefcd\u0060 | +| yellow 1000 | color | \u0060#542a00\u0060 | +| yellow 1100 | color | \u0060#2d1a05\u0060 | +| yellow 200 | color | \u0060#ffe99a\u0060 | +| yellow 300 | color | \u0060#ffe16e\u0060 | +| yellow 400 | color | \u0060#ffd943\u0060 | +| yellow 500 | color | \u0060#ffcd1c\u0060 | +| yellow 600 | color | \u0060#ffbc00\u0060 | +| yellow 700 | color | \u0060#dd9903\u0060 | +| yellow 800 | color | \u0060#ba7506\u0060 | +| yellow 900 | color | \u0060#944c0c\u0060 | +`; +/* end snapshot integration markdown markdown/table should match snapshot */ + +snapshots["integration markdown markdown/table with references should match snapshot"] = +` + + +| Token | Type | Value | +| --- | --- | --- | +| xl | dimension | \u00601\u0060 | +| large | dimension | \u00601\u0060 | +| medium | dimension | \u00601\u0060 | +| small | dimension | \u00600.5\u0060 | +| xl | fontSize | \u00602.25\u0060 | +| large | fontSize | \u00601.5\u0060 | +| medium | fontSize | \u00601\u0060 | +| small | fontSize | \u00600.75\u0060 | +| radius large | dimension | \u006030\u0060 | +| yellow 1100 | color | \u0060#2d1a05\u0060 | +| yellow 1000 | color | \u0060#542a00\u0060 | +| yellow 900 | color | \u0060#944c0c\u0060 | +| yellow 800 | color | \u0060#ba7506\u0060 | +| yellow 700 | color | \u0060#dd9903\u0060 | +| yellow 600 | color | \u0060#ffbc00\u0060 | +| yellow 500 | color | \u0060#ffcd1c\u0060 | +| yellow 400 | color | \u0060#ffd943\u0060 | +| yellow 300 | color | \u0060#ffe16e\u0060 | +| yellow 200 | color | \u0060#ffe99a\u0060 | +| yellow 100 | color | \u0060#fdefcd\u0060 | +| yellow 0 | color | \u0060#fff8e2\u0060 | +| neutral 1100 | color | \u0060#040404\u0060 | +| neutral 1000 | color | \u0060#162020\u0060 | +| neutral 900 | color | \u0060#273333\u0060 | +| neutral 800 | color | \u0060#364141\u0060 | +| neutral 700 | color | \u0060#515e5f\u0060 | +| neutral 600 | color | \u0060#6e797a\u0060 | +| neutral 500 | color | \u0060#929a9b\u0060 | +| neutral 400 | color | \u0060#b0b6b7\u0060 | +| neutral 300 | color | \u0060#c8cccc\u0060 | +| neutral 200 | color | \u0060#dee1e1\u0060 | +| neutral 100 | color | \u0060#f3f4f4\u0060 | +| neutral 0 | color | \u0060#FFFFFF\u0060 | +| orange 1100 | color | \u0060#2d130e\u0060 | +| orange 1000 | color | \u0060#601700\u0060 | +| orange 900 | color | \u0060#962c0b\u0060 | +| orange 800 | color | \u0060#ce5511\u0060 | +| orange 700 | color | \u0060#ed7024\u0060 | +| orange 600 | color | \u0060#f57d33\u0060 | +| orange 500 | color | \u0060#fc8943\u0060 | +| orange 400 | color | \u0060#ff9c5d\u0060 | +| orange 300 | color | \u0060#ffb180\u0060 | +| orange 200 | color | \u0060#ffc6a4\u0060 | +| orange 100 | color | \u0060#fcdccc\u0060 | +| orange 0 | color | \u0060#ffede3\u0060 | +| red 1100 | color | \u0060#2b1111\u0060 | +| red 1000 | color | \u0060#6d1313\u0060 | +| red 900 | color | \u0060#992222\u0060 | +| red 800 | color | \u0060#c63434\u0060 | +| red 700 | color | \u0060#db3e3e\u0060 | +| red 600 | color | \u0060#ed4c42\u0060 | +| red 500 | color | \u0060#f76054\u0060 | +| red 400 | color | \u0060#ff7f6e\u0060 | +| red 300 | color | \u0060#ff9c8f\u0060 | +| red 200 | color | \u0060#ffb8b1\u0060 | +| red 100 | color | \u0060#ffd5d2\u0060 | +| red 0 | color | \u0060#ffeae9\u0060 | +| pink 1100 | color | \u0060#2b1721\u0060 | +| pink 1000 | color | \u0060#561231\u0060 | +| pink 900 | color | \u0060#931847\u0060 | +| pink 800 | color | \u0060#b22f5b\u0060 | +| pink 700 | color | \u0060#ce3665\u0060 | +| pink 600 | color | \u0060#e0447c\u0060 | +| pink 500 | color | \u0060#ef588b\u0060 | +| pink 400 | color | \u0060#ff76ae\u0060 | +| pink 300 | color | \u0060#ff95c1\u0060 | +| pink 200 | color | \u0060#ffb5d5\u0060 | +| pink 100 | color | \u0060#fcdbeb\u0060 | +| pink 0 | color | \u0060#ffe9f3\u0060 | +| magenta 1100 | color | \u0060#29192d\u0060 | +| magenta 1000 | color | \u0060#451551\u0060 | +| magenta 900 | color | \u0060#6c2277\u0060 | +| magenta 800 | color | \u0060#8f3896\u0060 | +| magenta 700 | color | \u0060#ac44a8\u0060 | +| magenta 600 | color | \u0060#c44eb9\u0060 | +| magenta 500 | color | \u0060#db61db\u0060 | +| magenta 400 | color | \u0060#f282f5\u0060 | +| magenta 300 | color | \u0060#edadf2\u0060 | +| magenta 200 | color | \u0060#f4c4f7\u0060 | +| magenta 100 | color | \u0060#f9e3fc\u0060 | +| magenta 0 | color | \u0060#fef0ff\u0060 | +| purple 1100 | color | \u0060#1d1d38\u0060 | +| purple 1000 | color | \u0060#2d246b\u0060 | +| purple 900 | color | \u0060#483a9c\u0060 | +| purple 800 | color | \u0060#5e4eba\u0060 | +| purple 700 | color | \u0060#6f5ed3\u0060 | +| purple 600 | color | \u0060#816fea\u0060 | +| purple 500 | color | \u0060#9180f4\u0060 | +| purple 400 | color | \u0060#a193f2\u0060 | +| purple 300 | color | \u0060#c1c1f7\u0060 | +| purple 200 | color | \u0060#d8d7f9\u0060 | +| purple 100 | color | \u0060#eaeaf9\u0060 | +| purple 0 | color | \u0060#f2f2f9\u0060 | +| blue 1100 | color | \u0060#002138\u0060 | +| blue 1000 | color | \u0060#0a3960\u0060 | +| blue 900 | color | \u0060#0c5689\u0060 | +| blue 800 | color | \u0060#116daa\u0060 | +| blue 700 | color | \u0060#2079c3\u0060 | +| blue 600 | color | \u0060#2b87d3\u0060 | +| blue 500 | color | \u0060#3896e3\u0060 | +| blue 400 | color | \u0060#56adf5\u0060 | +| blue 300 | color | \u0060#a1d2f8\u0060 | +| blue 200 | color | \u0060#c7e4f9\u0060 | +| blue 100 | color | \u0060#dcf2ff\u0060 | +| blue 0 | color | \u0060#e9f8ff\u0060 | +| aqua 1100 | color | \u0060#002838\u0060 | +| aqua 1000 | color | \u0060#083d4f\u0060 | +| aqua 900 | color | \u0060#035e73\u0060 | +| aqua 800 | color | \u0060#0f6e84\u0060 | +| aqua 700 | color | \u0060#0b8599\u0060 | +| aqua 600 | color | \u0060#0797ae\u0060 | +| aqua 500 | color | \u0060#17b8ce\u0060 | +| aqua 400 | color | \u0060#33d6e2\u0060 | +| aqua 300 | color | \u0060#76e5e2\u0060 | +| aqua 200 | color | \u0060#a5f2f2\u0060 | +| aqua 100 | color | \u0060#c5f9f9\u0060 | +| aqua 0 | color | \u0060#d9fcfb\u0060 | +| teal 1100 | color | \u0060#002528\u0060 | +| teal 1000 | color | \u0060#083f3f\u0060 | +| teal 900 | color | \u0060#026661\u0060 | +| teal 800 | color | \u0060#067c7c\u0060 | +| teal 700 | color | \u0060#0b968f\u0060 | +| teal 600 | color | \u0060#00a99c\u0060 | +| teal 500 | color | \u0060#08c4b2\u0060 | +| teal 400 | color | \u0060#24e0c5\u0060 | +| teal 300 | color | \u0060#7dead5\u0060 | +| teal 200 | color | \u0060#b3f2e6\u0060 | +| teal 100 | color | \u0060#cdf7ef\u0060 | +| teal 0 | color | \u0060#e5f9f5\u0060 | +| green 1100 | color | \u0060#002b20\u0060 | +| green 1000 | color | \u0060#08422f\u0060 | +| green 900 | color | \u0060#006b40\u0060 | +| green 800 | color | \u0060#008b46\u0060 | +| green 700 | color | \u0060#0ca750\u0060 | +| green 600 | color | \u0060#2bb656\u0060 | +| green 500 | color | \u0060#59cb59\u0060 | +| green 400 | color | \u0060#75dd66\u0060 | +| green 300 | color | \u0060#98e58e\u0060 | +| green 200 | color | \u0060#c2f2bd\u0060 | +| green 100 | color | \u0060#d7f4d7\u0060 | +| green 0 | color | \u0060#ebf9eb\u0060 | +| success | color | \u0060{color.core.green.1000}\u0060 | +| warning | color | \u0060{color.core.orange.1000.value}\u0060 | +| danger | color | \u0060{color.core.red.1000.value}\u0060 | +| tertiary | color | \u0060{color.core.neutral.800.value}\u0060 | +| secondary | color | \u0060{color.core.neutral.900.value}\u0060 | +| primary | color | \u0060{color.core.neutral.1100.value}\u0060 | +| secondary | color | \u0060{color.core.purple.700.value}\u0060 | +| primary | color | \u0060{color.core.aqua.700.value}\u0060 | +| primary | color | \u0060{color.core.neutral.300.value}\u0060 | +| info | color | \u0060{color.core.blue.0.value}\u0060 | +| success | color | \u0060{color.core.green.0.value}\u0060 | +| warning | color | \u0060{color.core.orange.0.value}\u0060 | +| danger | color | \u0060{color.core.red.0.value}\u0060 | +| tertiary | color | \u0060{color.core.neutral.200.value}\u0060 | +| secondary | color | \u0060{color.core.neutral.100.value}\u0060 | +| primary | color | \u0060{color.core.neutral.0.value}\u0060 | +| interactive disabled | color | \u0060{color.font.tertiary.value}\u0060 | +| interactive active | color | \u0060{color.brand.secondary.value}\u0060 | +| interactive hover | color | \u0060{color.brand.primary.value}\u0060 | +| interactive _ | color | \u0060{color.brand.primary.value}\u0060 | +| disabled | color | \u0060{color.background.tertiary.value}\u0060 | +`; +/* end snapshot integration markdown markdown/table with references should match snapshot */ + diff --git a/__integration__/markdown.test.js b/__integration__/markdown.test.js new file mode 100644 index 000000000..e00e0953e --- /dev/null +++ b/__integration__/markdown.test.js @@ -0,0 +1,70 @@ +/* + * Copyright Target Corporation. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { expect } from 'chai'; +import StyleDictionary from 'style-dictionary'; +import { fs } from 'style-dictionary/fs'; +import { resolve } from '../lib/resolve.js'; +import { buildPath } from './_constants.js'; +import { clearOutput } from '../__tests__/__helpers.js'; + +describe('integration', async () => { + before(async () => { + const sd = new StyleDictionary({ + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + markdown: { + transformGroup: `markdown`, + buildPath, + files: [ + { + destination: 'StyleDictionary.md', + format: 'markdown/table', + }, + { + destination: 'StyleDictionaryWithReferences.md', + format: 'markdown/table', + options: { + outputReferences: true, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + }); + + afterEach(() => { + clearOutput(buildPath); + }); + + describe('markdown', async () => { + describe(`markdown/table`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}StyleDictionary.md`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); + }); + + describe(`with references`, async () => { + it(`should match snapshot`, async () => { + const output = fs.readFileSync(resolve(`${buildPath}StyleDictionaryWithReferences.md`), { + encoding: `UTF-8`, + }); + await expect(output).to.matchSnapshot(); + }); + }); + }); + }); +}); diff --git a/__tests__/formats/__snapshots__/all.test.snap.js b/__tests__/formats/__snapshots__/all.test.snap.js index 2eed5c385..2843f047c 100644 --- a/__tests__/formats/__snapshots__/all.test.snap.js +++ b/__tests__/formats/__snapshots__/all.test.snap.js @@ -1513,3 +1513,28 @@ class { }`; /* end snapshot formats all should match flutter/class.dart snapshot with fileHeaderTimestamp set */ +snapshots["formats all should match markdown/table snapshot"] = +` + + +| Token | Type | Value | +| --- | --- | --- | +| color_red | undefined | \u0060#FF0000\u0060 | +`; +/* end snapshot formats all should match markdown/table snapshot */ + +snapshots["formats all should match markdown/table snapshot with fileHeaderTimestamp set"] = +` + + +| Token | Type | Value | +| --- | --- | --- | +| color_red | undefined | \u0060#FF0000\u0060 | +`; +/* end snapshot formats all should match markdown/table snapshot with fileHeaderTimestamp set */ + diff --git a/docs/src/content/docs/reference/Hooks/Formats/index.md b/docs/src/content/docs/reference/Hooks/Formats/index.md index dd6ed1262..c1fdf2959 100644 --- a/docs/src/content/docs/reference/Hooks/Formats/index.md +++ b/docs/src/content/docs/reference/Hooks/Formats/index.md @@ -177,6 +177,7 @@ Not all formats use the `outputReferences` option because that file format might - [compose/object](predefined/#composeobject) - [ios-swift/class.swift](predefined/#ios-swiftclassswift) - [flutter/class.dart](predefined/#flutterclassdart) +- [markdown/table](predefined/#markdowntable) You can create custom formats that output references as well. See the [Custom format with output references](#custom-format-with-output-references) section. diff --git a/docs/src/content/docs/reference/Hooks/Formats/predefined.md b/docs/src/content/docs/reference/Hooks/Formats/predefined.md index e299f7489..3c19e8be6 100644 --- a/docs/src/content/docs/reference/Hooks/Formats/predefined.md +++ b/docs/src/content/docs/reference/Hooks/Formats/predefined.md @@ -911,3 +911,24 @@ class StyleDictionary { ``` --- + +### markdown/table + +Creates a Markdown file containing a table with a row for each property. + +| Param | Type | Description | +| ------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `options` | `Object` | | +| `options.showFileHeader` | `boolean` | Whether or not to include a comment that has the build date. Defaults to `true` | +| `options.showDescriptionColumn` | `boolean` | Whether or not to include the description column in the table. Defaults to `false` | +| `options.outputReferences` | `boolean \| OutputReferencesFunction` | Whether or not to keep [references](#references-in-output-files) (a -> b -> c) in the output. Defaults to `false`. Also allows passing a function to conditionally output references on a per token basis. | + +Example: + +```md title="colors.md" +| Token | Type | Value | +| ----- | ----- | ----------- | +| red 5 | color | `#fffaf3f2` | +``` + +--- diff --git a/docs/src/content/docs/reference/Hooks/Transform Groups/predefined.md b/docs/src/content/docs/reference/Hooks/Transform Groups/predefined.md index 2479137b2..5e95e22f2 100644 --- a/docs/src/content/docs/reference/Hooks/Transform Groups/predefined.md +++ b/docs/src/content/docs/reference/Hooks/Transform Groups/predefined.md @@ -211,3 +211,12 @@ Transforms: [name/camel](/reference/hooks/transforms/predefined#namecamel) [size/object](/reference/hooks/transforms/predefined#sizeobject) [color/css](/reference/hooks/transforms/predefined#colorcss) + +--- + +### markdown + +Transforms: + +[attribute/cti](/reference/hooks/transforms/predefined#attributecti) +[name/human](/reference/hooks/transforms/predefined#namehuman) diff --git a/lib/common/formats.js b/lib/common/formats.js index 88f95345b..b8061c15f 100644 --- a/lib/common/formats.js +++ b/lib/common/formats.js @@ -45,6 +45,7 @@ import scssMapDeep from './templates/scss/map-deep.template.js'; import scssMapFlat from './templates/scss/map-flat.template.js'; import macrosTemplate from './templates/ios/macros.template.js'; import plistTemplate from './templates/ios/plist.template.js'; +import markdownTable from './templates/markdown/table.md.template.js'; /** * @typedef {import('../../types/Format.ts').Format} Format @@ -1532,6 +1533,50 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul }); return flutterClassDart({ allTokens: sortedTokens, file, options, formatProperty, header }); }, + + // Markdown templates + /** + * Creates a Markdown file containing a table with a row for each property. + * + * @memberof Formats + * @kind member + * @typedef {Object} markdownTableOpts + * @property {boolean} [markdownTableOpts.showFileHeader=true] - Whether or not to include a comment that has the build date + * @property {boolean} [markdownTableOpts.showDescriptionColumn=false] - Whether or not to show the description column in the table + * @property {OutputReferences} [markdownTableOpts.outputReferences=false] - Whether or not to keep [references](/#/formats?id=references-in-output-files) (a -> b -> c) in the output. + * @param {FormatArgs & { options?: markdownTableOpts }} options + * @example + * ```md + * | Token | Type | Value | + * | --- | --- | --- | + * | red 5 | color | `#fffaf3f2` | + * ``` + */ + 'markdown/table': async function ({ dictionary, options, file }) { + const { allTokens, tokens, unfilteredTokens } = dictionary; + const { outputReferences, formatting, usesDtcg } = options; + const formatProperty = createPropertyFormatter({ + outputReferences, + dictionary, + formatting, + usesDtcg, + }); + + let sortedTokens; + if (outputReferences) { + sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens })); + } else { + sortedTokens = [...allTokens].sort(sortByName); + } + + const header = await fileHeader({ + file, + commentStyle: 'xml', + formatting: getFormattingCloneWithoutPrefix(formatting), + options, + }); + return markdownTable({ allTokens: sortedTokens, options, formatProperty, header }); + }, }; // Mark which formats are nested diff --git a/lib/common/templates/markdown/table.md.template.js b/lib/common/templates/markdown/table.md.template.js new file mode 100644 index 000000000..c17cfae28 --- /dev/null +++ b/lib/common/templates/markdown/table.md.template.js @@ -0,0 +1,30 @@ +/** + * @typedef {import('../../../../types/DesignToken.ts').TransformedToken} TransformedToken + * @typedef {import('../../../../types/Config.ts').Config} Config + * @typedef {import('../../../../types/Config.ts').LocalOptions} LocalOptions + */ + +/** + * @param {{ + * allTokens: TransformedToken[] + * formatProperty: (token: TransformedToken) => string + * options: Config & LocalOptions + * header: string + * }} opts + */ +export default ({ allTokens, formatProperty, options, header }) => { + const hasDescription = options.showDescriptionColumn; + + return ` +${header} + +| Token | ${hasDescription ? 'Description | ' : ''}Type | Value | +| --- | ${hasDescription ? '--- | ' : ''}--- | --- | +${allTokens + .map( + (token) => + `| ${token.name.replace(/ $/, '')} | ${hasDescription ? (token.$description ? token.$description : token.comment ? token.comment : '') + ' | ' : ''}${token.original.type} | \u0060${options.usesDtcg ? JSON.stringify(token.original.$value) : token.original.value}\u0060 |`, + ) + .join('\n')} +`; +}; diff --git a/lib/common/transformGroups.js b/lib/common/transformGroups.js index 27e509d5b..75e27a06d 100644 --- a/lib/common/transformGroups.js +++ b/lib/common/transformGroups.js @@ -322,4 +322,14 @@ export default { * @memberof TransformGroups */ 'react-native': ['name/camel', 'color/css', 'size/object'], + + /** + * Transforms: + * + * [attribute/cti](/reference/hooks/transforms/predefined#attributecti) + * [name/human](/reference/hooks/transforms/predefined#namehuman) + * + * @memberof TransformGroups + */ + markdown: ['attribute/cti', 'name/human'], };