diff --git a/.pnp.cjs b/.pnp.cjs index 375e2a21e..4db9233f5 100644 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -42,6 +42,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fullcalendar/luxon2", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.11.3"],\ ["@fullcalendar/timegrid", "npm:5.11.3"],\ ["@fullcalendar/vue3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.11.3"],\ + ["@parcel/optimizer-data-url", "npm:2.8.0"],\ + ["@parcel/transformer-inline-string", "npm:2.8.0"],\ ["@parcel/transformer-sass", "npm:2.8.0"],\ ["@popperjs/core", "npm:2.11.6"],\ ["@rollup/pluginutils", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.0.2"],\ @@ -52,7 +54,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["browser-fs-access", "npm:0.31.1"],\ ["browserlist", "npm:1.0.1"],\ ["c8", "npm:7.12.0"],\ - ["caniuse-lite", "npm:1.0.30001434"],\ + ["caniuse-lite", "npm:1.0.30001435"],\ ["d3", "npm:7.6.1"],\ ["eslint", "npm:8.28.0"],\ ["eslint-config-standard", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:17.0.0"],\ @@ -63,7 +65,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["eslint-plugin-promise", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.1"],\ ["eslint-plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:9.8.0"],\ ["file-saver", "npm:2.0.5"],\ - ["highcharts", "npm:10.3.1"],\ + ["highcharts", "npm:10.3.2"],\ ["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:7.10.0"],\ ["jquery", "npm:3.6.1"],\ ["jquery-migrate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:3.4.0"],\ @@ -72,14 +74,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["list.js", "npm:2.3.1"],\ ["lodash", "npm:4.17.21"],\ ["lodash-es", "npm:4.17.21"],\ - ["luxon", "npm:3.1.0"],\ + ["luxon", "npm:3.1.1"],\ ["moment", "npm:2.29.4"],\ ["moment-timezone", "npm:0.5.39"],\ ["ms", "npm:2.1.3"],\ ["murmurhash-js", "npm:1.0.0"],\ ["naive-ui", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.34.2"],\ ["parcel", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.8.0"],\ - ["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.26"],\ + ["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.27"],\ ["pinia-plugin-persist", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:1.0.0"],\ ["pug", "npm:3.0.2"],\ ["sass", "npm:1.56.1"],\ @@ -337,7 +339,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fullcalendar/luxon2", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.11.3"],\ ["@fullcalendar/common", "npm:5.11.3"],\ ["@types/luxon", null],\ - ["luxon", "npm:3.1.0"],\ + ["luxon", "npm:3.1.1"],\ ["tslib", "npm:2.4.0"]\ ],\ "packagePeers": [\ @@ -1136,6 +1138,19 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@parcel/optimizer-data-url", [\ + ["npm:2.8.0", {\ + "packageLocation": "./.yarn/cache/@parcel-optimizer-data-url-npm-2.8.0-89a39d906e-998fb94cee.zip/node_modules/@parcel/optimizer-data-url/",\ + "packageDependencies": [\ + ["@parcel/optimizer-data-url", "npm:2.8.0"],\ + ["@parcel/plugin", "npm:2.8.0"],\ + ["@parcel/utils", "npm:2.8.0"],\ + ["isbinaryfile", "npm:4.0.10"],\ + ["mime", "npm:2.6.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@parcel/optimizer-htmlnano", [\ ["npm:2.8.0", {\ "packageLocation": "./.yarn/cache/@parcel-optimizer-htmlnano-npm-2.8.0-d2ead43d0c-68010e586b.zip/node_modules/@parcel/optimizer-htmlnano/",\ @@ -1529,6 +1544,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@parcel/transformer-inline-string", [\ + ["npm:2.8.0", {\ + "packageLocation": "./.yarn/cache/@parcel-transformer-inline-string-npm-2.8.0-5fce2c90b8-e40616c55b.zip/node_modules/@parcel/transformer-inline-string/",\ + "packageDependencies": [\ + ["@parcel/transformer-inline-string", "npm:2.8.0"],\ + ["@parcel/plugin", "npm:2.8.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@parcel/transformer-js", [\ ["npm:2.8.0", {\ "packageLocation": "./.yarn/unplugged/@parcel-transformer-js-virtual-0a5c0b53bd/node_modules/@parcel/transformer-js/",\ @@ -2690,10 +2715,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "HARD"\ }],\ - ["npm:1.0.30001434", {\ - "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001434-9c6ea57daf-7c9d2641e8.zip/node_modules/caniuse-lite/",\ + ["npm:1.0.30001435", {\ + "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001435-7cebb35f0a-ec88b9c37f.zip/node_modules/caniuse-lite/",\ "packageDependencies": [\ - ["caniuse-lite", "npm:1.0.30001434"]\ + ["caniuse-lite", "npm:1.0.30001435"]\ ],\ "linkType": "HARD"\ }]\ @@ -4910,10 +4935,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["highcharts", [\ - ["npm:10.3.1", {\ - "packageLocation": "./.yarn/cache/highcharts-npm-10.3.1-e67a887ff6-8a1cf9a363.zip/node_modules/highcharts/",\ + ["npm:10.3.2", {\ + "packageLocation": "./.yarn/cache/highcharts-npm-10.3.2-1672942f09-43cb42b24c.zip/node_modules/highcharts/",\ "packageDependencies": [\ - ["highcharts", "npm:10.3.1"]\ + ["highcharts", "npm:10.3.2"]\ ],\ "linkType": "HARD"\ }]\ @@ -5456,6 +5481,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["isbinaryfile", [\ + ["npm:4.0.10", {\ + "packageLocation": "./.yarn/cache/isbinaryfile-npm-4.0.10-91d1251522-a6b28db7e2.zip/node_modules/isbinaryfile/",\ + "packageDependencies": [\ + ["isbinaryfile", "npm:4.0.10"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["isexe", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/isexe-npm-2.0.0-b58870bd2e-26bf6c5480.zip/node_modules/isexe/",\ @@ -5918,10 +5952,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["luxon", [\ - ["npm:3.1.0", {\ - "packageLocation": "./.yarn/cache/luxon-npm-3.1.0-16e2508500-f8a850b759.zip/node_modules/luxon/",\ + ["npm:3.1.1", {\ + "packageLocation": "./.yarn/cache/luxon-npm-3.1.1-64fe977c1d-388fb35d3c.zip/node_modules/luxon/",\ "packageDependencies": [\ - ["luxon", "npm:3.1.0"]\ + ["luxon", "npm:3.1.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -5987,6 +6021,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["mime", "npm:1.6.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.6.0", {\ + "packageLocation": "./.yarn/cache/mime-npm-2.6.0-88b89d8de0-1497ba7b9f.zip/node_modules/mime/",\ + "packageDependencies": [\ + ["mime", "npm:2.6.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["minimatch", [\ @@ -6659,17 +6700,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["pinia", [\ - ["npm:2.0.26", {\ - "packageLocation": "./.yarn/cache/pinia-npm-2.0.26-0d96417fac-0d38cc0efc.zip/node_modules/pinia/",\ + ["npm:2.0.27", {\ + "packageLocation": "./.yarn/cache/pinia-npm-2.0.27-3e0154e702-29c862ea43.zip/node_modules/pinia/",\ "packageDependencies": [\ - ["pinia", "npm:2.0.26"]\ + ["pinia", "npm:2.0.27"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.26", {\ - "packageLocation": "./.yarn/__virtual__/pinia-virtual-3c74e5a139/0/cache/pinia-npm-2.0.26-0d96417fac-0d38cc0efc.zip/node_modules/pinia/",\ + ["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.27", {\ + "packageLocation": "./.yarn/__virtual__/pinia-virtual-0b7bfddb52/0/cache/pinia-npm-2.0.27-3e0154e702-29c862ea43.zip/node_modules/pinia/",\ "packageDependencies": [\ - ["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.26"],\ + ["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.27"],\ ["@types/typescript", null],\ ["@types/vue", null],\ ["@types/vue__composition-api", null],\ @@ -6677,7 +6718,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@vue/devtools-api", "npm:6.4.5"],\ ["typescript", null],\ ["vue", "npm:3.2.45"],\ - ["vue-demi", "virtual:3c74e5a1392a9d26efc27d5867a5220b1ab24b8bfb7c76fe2dac826f7e9d478b9c8eb69cc87331bb2ba20521466999017a02e9dca572946a787e2b4314602fca#npm:0.13.1"]\ + ["vue-demi", "virtual:0b7bfddb52b3cb488814806546397e52c62caef1815758033c8eac7ce386779ac52132e251ad567a19dde858cd2ed318ab2b52e9e258efd261b951e0d2160c16#npm:0.13.1"]\ ],\ "packagePeers": [\ "@types/typescript",\ @@ -6706,7 +6747,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/vue", null],\ ["@types/vue__composition-api", null],\ ["@vue/composition-api", null],\ - ["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.26"],\ + ["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.27"],\ ["vue", "npm:3.2.45"],\ ["vue-demi", "virtual:f56fcf19bbebc2ada1b28955da8cc216b1e9a569a1a7337d2d1926c1ebd1bc7a5bd91aedae1d05c15c8562f33caf7c59bd3020a667340f6bdc6a7b13fc2ba847#npm:0.12.5"]\ ],\ @@ -7232,6 +7273,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fullcalendar/luxon2", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.11.3"],\ ["@fullcalendar/timegrid", "npm:5.11.3"],\ ["@fullcalendar/vue3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.11.3"],\ + ["@parcel/optimizer-data-url", "npm:2.8.0"],\ + ["@parcel/transformer-inline-string", "npm:2.8.0"],\ ["@parcel/transformer-sass", "npm:2.8.0"],\ ["@popperjs/core", "npm:2.11.6"],\ ["@rollup/pluginutils", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.0.2"],\ @@ -7242,7 +7285,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["browser-fs-access", "npm:0.31.1"],\ ["browserlist", "npm:1.0.1"],\ ["c8", "npm:7.12.0"],\ - ["caniuse-lite", "npm:1.0.30001434"],\ + ["caniuse-lite", "npm:1.0.30001435"],\ ["d3", "npm:7.6.1"],\ ["eslint", "npm:8.28.0"],\ ["eslint-config-standard", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:17.0.0"],\ @@ -7253,7 +7296,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["eslint-plugin-promise", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.1"],\ ["eslint-plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:9.8.0"],\ ["file-saver", "npm:2.0.5"],\ - ["highcharts", "npm:10.3.1"],\ + ["highcharts", "npm:10.3.2"],\ ["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:7.10.0"],\ ["jquery", "npm:3.6.1"],\ ["jquery-migrate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:3.4.0"],\ @@ -7262,14 +7305,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["list.js", "npm:2.3.1"],\ ["lodash", "npm:4.17.21"],\ ["lodash-es", "npm:4.17.21"],\ - ["luxon", "npm:3.1.0"],\ + ["luxon", "npm:3.1.1"],\ ["moment", "npm:2.29.4"],\ ["moment-timezone", "npm:0.5.39"],\ ["ms", "npm:2.1.3"],\ ["murmurhash-js", "npm:1.0.0"],\ ["naive-ui", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.34.2"],\ ["parcel", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.8.0"],\ - ["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.26"],\ + ["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.0.27"],\ ["pinia-plugin-persist", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:1.0.0"],\ ["pug", "npm:3.0.2"],\ ["sass", "npm:1.56.1"],\ @@ -8159,16 +8202,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "SOFT"\ }],\ ["npm:0.13.1", {\ - "packageLocation": "./.yarn/unplugged/vue-demi-virtual-cfef5ecd67/node_modules/vue-demi/",\ + "packageLocation": "./.yarn/unplugged/vue-demi-virtual-615072ef29/node_modules/vue-demi/",\ "packageDependencies": [\ ["vue-demi", "npm:0.13.1"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:3c74e5a1392a9d26efc27d5867a5220b1ab24b8bfb7c76fe2dac826f7e9d478b9c8eb69cc87331bb2ba20521466999017a02e9dca572946a787e2b4314602fca#npm:0.13.1", {\ - "packageLocation": "./.yarn/unplugged/vue-demi-virtual-cfef5ecd67/node_modules/vue-demi/",\ + ["virtual:0b7bfddb52b3cb488814806546397e52c62caef1815758033c8eac7ce386779ac52132e251ad567a19dde858cd2ed318ab2b52e9e258efd261b951e0d2160c16#npm:0.13.1", {\ + "packageLocation": "./.yarn/unplugged/vue-demi-virtual-615072ef29/node_modules/vue-demi/",\ "packageDependencies": [\ - ["vue-demi", "virtual:3c74e5a1392a9d26efc27d5867a5220b1ab24b8bfb7c76fe2dac826f7e9d478b9c8eb69cc87331bb2ba20521466999017a02e9dca572946a787e2b4314602fca#npm:0.13.1"],\ + ["vue-demi", "virtual:0b7bfddb52b3cb488814806546397e52c62caef1815758033c8eac7ce386779ac52132e251ad567a19dde858cd2ed318ab2b52e9e258efd261b951e0d2160c16#npm:0.13.1"],\ ["@types/vue", null],\ ["@types/vue__composition-api", null],\ ["@vue/composition-api", null],\ diff --git a/.yarn/cache/@parcel-optimizer-data-url-npm-2.8.0-89a39d906e-998fb94cee.zip b/.yarn/cache/@parcel-optimizer-data-url-npm-2.8.0-89a39d906e-998fb94cee.zip new file mode 100644 index 000000000..a0ad46637 Binary files /dev/null and b/.yarn/cache/@parcel-optimizer-data-url-npm-2.8.0-89a39d906e-998fb94cee.zip differ diff --git a/.yarn/cache/@parcel-transformer-inline-string-npm-2.8.0-5fce2c90b8-e40616c55b.zip b/.yarn/cache/@parcel-transformer-inline-string-npm-2.8.0-5fce2c90b8-e40616c55b.zip new file mode 100644 index 000000000..5598830cd Binary files /dev/null and b/.yarn/cache/@parcel-transformer-inline-string-npm-2.8.0-5fce2c90b8-e40616c55b.zip differ diff --git a/.yarn/cache/caniuse-lite-npm-1.0.30001434-9c6ea57daf-7c9d2641e8.zip b/.yarn/cache/caniuse-lite-npm-1.0.30001434-9c6ea57daf-7c9d2641e8.zip deleted file mode 100644 index daa4e7488..000000000 Binary files a/.yarn/cache/caniuse-lite-npm-1.0.30001434-9c6ea57daf-7c9d2641e8.zip and /dev/null differ diff --git a/.yarn/cache/caniuse-lite-npm-1.0.30001435-7cebb35f0a-ec88b9c37f.zip b/.yarn/cache/caniuse-lite-npm-1.0.30001435-7cebb35f0a-ec88b9c37f.zip new file mode 100644 index 000000000..9851a7ce7 Binary files /dev/null and b/.yarn/cache/caniuse-lite-npm-1.0.30001435-7cebb35f0a-ec88b9c37f.zip differ diff --git a/.yarn/cache/highcharts-npm-10.3.1-e67a887ff6-8a1cf9a363.zip b/.yarn/cache/highcharts-npm-10.3.2-1672942f09-43cb42b24c.zip similarity index 63% rename from .yarn/cache/highcharts-npm-10.3.1-e67a887ff6-8a1cf9a363.zip rename to .yarn/cache/highcharts-npm-10.3.2-1672942f09-43cb42b24c.zip index 4713b4599..410fae01e 100644 Binary files a/.yarn/cache/highcharts-npm-10.3.1-e67a887ff6-8a1cf9a363.zip and b/.yarn/cache/highcharts-npm-10.3.2-1672942f09-43cb42b24c.zip differ diff --git a/.yarn/cache/isbinaryfile-npm-4.0.10-91d1251522-a6b28db7e2.zip b/.yarn/cache/isbinaryfile-npm-4.0.10-91d1251522-a6b28db7e2.zip new file mode 100644 index 000000000..33eb2b844 Binary files /dev/null and b/.yarn/cache/isbinaryfile-npm-4.0.10-91d1251522-a6b28db7e2.zip differ diff --git a/.yarn/cache/luxon-npm-3.1.0-16e2508500-f8a850b759.zip b/.yarn/cache/luxon-npm-3.1.0-16e2508500-f8a850b759.zip deleted file mode 100644 index 6a145dd08..000000000 Binary files a/.yarn/cache/luxon-npm-3.1.0-16e2508500-f8a850b759.zip and /dev/null differ diff --git a/.yarn/cache/luxon-npm-3.1.1-64fe977c1d-388fb35d3c.zip b/.yarn/cache/luxon-npm-3.1.1-64fe977c1d-388fb35d3c.zip new file mode 100644 index 000000000..1e0c7262f Binary files /dev/null and b/.yarn/cache/luxon-npm-3.1.1-64fe977c1d-388fb35d3c.zip differ diff --git a/.yarn/cache/mime-npm-2.6.0-88b89d8de0-1497ba7b9f.zip b/.yarn/cache/mime-npm-2.6.0-88b89d8de0-1497ba7b9f.zip new file mode 100644 index 000000000..644ef2b53 Binary files /dev/null and b/.yarn/cache/mime-npm-2.6.0-88b89d8de0-1497ba7b9f.zip differ diff --git a/.yarn/cache/pinia-npm-2.0.26-0d96417fac-0d38cc0efc.zip b/.yarn/cache/pinia-npm-2.0.26-0d96417fac-0d38cc0efc.zip deleted file mode 100644 index c7cad55cd..000000000 Binary files a/.yarn/cache/pinia-npm-2.0.26-0d96417fac-0d38cc0efc.zip and /dev/null differ diff --git a/.yarn/cache/pinia-npm-2.0.27-3e0154e702-29c862ea43.zip b/.yarn/cache/pinia-npm-2.0.27-3e0154e702-29c862ea43.zip new file mode 100644 index 000000000..c0477d355 Binary files /dev/null and b/.yarn/cache/pinia-npm-2.0.27-3e0154e702-29c862ea43.zip differ diff --git a/dev/tests/debug.sh b/dev/tests/debug.sh new file mode 100644 index 000000000..37e7bc3ab --- /dev/null +++ b/dev/tests/debug.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# This script recreate the same environment used during tests on GitHub Actions +# and drops you into a terminal at the point where the actual tests would be run. +# +# Refer to https://github.com/ietf-tools/datatracker/blob/main/.github/workflows/build.yml#L141-L155 +# for the commands to run next. +# +# Simply type "exit" + ENTER to exit and shutdown this test environment. + +echo "Fetching latest images..." +docker pull ghcr.io/ietf-tools/datatracker-app-base:latest +docker pull ghcr.io/ietf-tools/datatracker-db:latest +echo "Starting containers..." +docker compose -f docker-compose.debug.yml -p dtdebug up -d +echo "Copying working directory into container..." +docker compose -p dtdebug cp ../../. app:/__w/datatracker/datatracker/ +echo "Run prepare script..." +docker compose -p dtdebug exec app chmod +x ./dev/tests/prepare.sh +docker compose -p dtdebug exec app sh ./dev/tests/prepare.sh +docker compose -p dtdebug exec app /usr/local/bin/wait-for db:3306 -- echo "DB ready" +echo "=================================================================" +echo "Launching zsh terminal:" +docker compose -p dtdebug exec app /bin/zsh +echo "Shutting down containers..." +docker compose -p dtdebug down -v diff --git a/dev/tests/docker-compose.debug.yml b/dev/tests/docker-compose.debug.yml new file mode 100644 index 000000000..44649c117 --- /dev/null +++ b/dev/tests/docker-compose.debug.yml @@ -0,0 +1,33 @@ +# This docker-compose replicates the test workflow happening on GitHub during a PR / build check. +# To be used from the debug.sh script. + +version: '3.8' + +services: + app: + image: ghcr.io/ietf-tools/datatracker-app-base:latest + command: -f /dev/null + working_dir: /__w/datatracker/datatracker + entrypoint: tail + hostname: app + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + CI: 'true' + GITHUB_ACTIONS: 'true' + HOME: /github/home + db: + image: ghcr.io/ietf-tools/datatracker-db:latest + restart: unless-stopped + volumes: + - mariadb-data:/var/lib/mysql + environment: + MYSQL_ROOT_PASSWORD: RkTkDPFnKpko + MYSQL_DATABASE: ietf_utf8 + MYSQL_USER: django + MYSQL_PASSWORD: RkTkDPFnKpko + CI: 'true' + GITHUB_ACTIONS: 'true' + +volumes: + mariadb-data: diff --git a/ietf/doc/models.py b/ietf/doc/models.py index bb2175355..cc01f9756 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -8,6 +8,8 @@ import io import os import rfc2html +from pathlib import Path +from lxml import etree from typing import Optional, TYPE_CHECKING from weasyprint import HTML as wpHTML @@ -21,6 +23,7 @@ from django.conf import settings from django.utils import timezone from django.utils.encoding import force_text from django.utils.html import mark_safe # type:ignore +from django.contrib.staticfiles import finders import debug # pyflakes:ignore @@ -541,6 +544,46 @@ class DocumentInfo(models.Model): def text_or_error(self): return self.text() or "Error; cannot read '%s'"%self.get_base_name() + def html_body(self, classes=""): + if self.get_state_slug() == "rfc": + try: + html = Path( + os.path.join(settings.RFC_PATH, self.canonical_name() + ".html") + ).read_text() + except IOError: + return None + else: + try: + html = Path( + os.path.join( + settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR, + self.name + "-" + self.rev + ".html", + ) + ).read_text() + except IOError: + return None + + # If HTML was generated by rfc2html, do not return it. Caller + # will use htmlize() to use a more current rfc2html to + # generate an HTMLized version. TODO: There should be a + # better way to determine how an HTML format was generated. + if html.startswith("
"): + return None + + # get body + body = etree.HTML(html).xpath("//body")[0] + body.tag = "div" + if classes: + body.attrib["class"] = classes + + # remove things + for tag in ["script"]: + for t in body.xpath(f"//{tag}"): + t.getparent().remove(t) + html = etree.tostring(body, encoding=str, method="html") + + return html + def htmlized(self): name = self.get_base_name() text = self.text() @@ -566,17 +609,29 @@ class DocumentInfo(models.Model): def pdfized(self): name = self.get_base_name() - text = self.text() - cache = caches['pdfized'] - cache_key = name.split('.')[0] + text = self.html_body(classes="rfchtml") + stylesheets = [finders.find("ietf/css/document_html_referenced.css")] + if text: + stylesheets.append(finders.find("ietf/css/document_html_txt.css")) + else: + text = self.htmlized() + stylesheets.append(io.BytesIO(b"body { font-size: 9.2pt; }")) + + cache = caches["pdfized"] + cache_key = name.split(".")[0] try: pdf = cache.get(cache_key) except EOFError: pdf = None if not pdf: - html = rfc2html.markup(text, path=settings.PDFIZER_URL_PREFIX) try: - pdf = wpHTML(string=html.replace('\xad','')).write_pdf(stylesheets=[io.BytesIO(b'html { font-size: 94%;}')]) + pdf = wpHTML( + string=text, base_url=settings.IDTRACKER_BASE_URL + ).write_pdf( + stylesheets=stylesheets, + presentational_hints=True, + optimize_size=("fonts", "images"), + ) except AssertionError: pdf = None if pdf: diff --git a/ietf/doc/templatetags/ietf_filters.py b/ietf/doc/templatetags/ietf_filters.py index e5353d1de..1137cf636 100644 --- a/ietf/doc/templatetags/ietf_filters.py +++ b/ietf/doc/templatetags/ietf_filters.py @@ -260,8 +260,8 @@ def urlize_ietf_docs(string, autoescape=None): urlize_ietf_docs = stringfilter(urlize_ietf_docs) -@register.filter(name='urlize_related_source_list', is_safe=True, needs_autoescape=True) -def urlize_related_source_list(related, autoescape=None): +@register.filter(name='urlize_related_source_list', is_safe=True, document_html=False) +def urlize_related_source_list(related, document_html=False): """Convert a list of RelatedDocuments into list of links using the source document's canonical name""" links = [] names = set() @@ -273,10 +273,9 @@ def urlize_related_source_list(related, autoescape=None): continue names.add(name) titles.add(title) - url = urlreverse('ietf.doc.views_doc.document_main', kwargs=dict(name=name)) - if autoescape: - name = escape(name) - title = escape(title) + url = urlreverse('ietf.doc.views_doc.document_main' if document_html is False else 'ietf.doc.views_doc.document_html', kwargs=dict(name=name)) + name = escape(name) + title = escape(title) links.append(mark_safe( '%(name)s' % dict(name=prettify_std_name(name), title=title, @@ -284,17 +283,16 @@ def urlize_related_source_list(related, autoescape=None): )) return links -@register.filter(name='urlize_related_target_list', is_safe=True, needs_autoescape=True) -def urlize_related_target_list(related, autoescape=None): +@register.filter(name='urlize_related_target_list', is_safe=True, document_html=False) +def urlize_related_target_list(related, document_html=False): """Convert a list of RelatedDocuments into list of links using the target document's canonical name""" links = [] for rel in related: name=rel.target.document.canonical_name() title = rel.target.document.title - url = urlreverse('ietf.doc.views_doc.document_main', kwargs=dict(name=name)) - if autoescape: - name = escape(name) - title = escape(title) + url = urlreverse('ietf.doc.views_doc.document_main' if document_html is False else 'ietf.doc.views_doc.document_html', kwargs=dict(name=name)) + name = escape(name) + title = escape(title) links.append(mark_safe( '%(name)s' % dict(name=prettify_std_name(name), title=title, @@ -554,6 +552,19 @@ def consensus(doc): else: return "Unknown" + +@register.filter +def std_level_to_label_format(doc): + """Returns valid Bootstrap classes to label a status level badge.""" + if doc.is_rfc(): + if doc.related_that("obs"): + return "obs" + else: + return doc.std_level_id + else: + return "draft" + + @register.filter def pos_to_label_format(text): """Returns valid Bootstrap classes to label a ballot position.""" diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py index 533c61fd5..751625e59 100644 --- a/ietf/doc/tests.py +++ b/ietf/doc/tests.py @@ -730,13 +730,13 @@ Man Expires September 22, 2015 [Page 3] r = self.client.get(urlreverse("ietf.doc.views_doc.document_html", kwargs=dict(name=draft.name))) self.assertEqual(r.status_code, 200) - self.assertContains(r, "Versions:") + self.assertContains(r, "Select version") self.assertContains(r, "Deimos street") q = PyQuery(r.content) self.assertEqual(q('title').text(), 'draft-ietf-mars-test-01') - self.assertEqual(len(q('.rfcmarkup pre')), 4) - self.assertEqual(len(q('.rfcmarkup span.h1')), 2) - self.assertEqual(len(q('.rfcmarkup a[href]')), 41) + self.assertEqual(len(q('.rfcmarkup pre')), 3) + self.assertEqual(len(q('.rfcmarkup span.h1, .rfcmarkup h1')), 2) + self.assertEqual(len(q('.rfcmarkup a[href]')), 28) r = self.client.get(urlreverse("ietf.doc.views_doc.document_html", kwargs=dict(name=draft.name, rev=draft.rev))) self.assertEqual(r.status_code, 200) diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index 27d36284a..1824123ca 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -995,41 +995,6 @@ def get_search_cache_key(params): key = "doc:document:search:" + hashlib.sha512(json.dumps(kwargs, sort_keys=True).encode('utf-8')).hexdigest() return key -def label_wrap(label, items, joiner=',', max=50): - lines = [] - if not items: - return lines - line = '%s: %s' % (label, items[0]) - for item in items[1:]: - if len(line)+len(joiner+' ')+len(item) > max: - lines.append(line+joiner) - line = ' '*(len(label)+len(': ')) + item - else: - line += joiner+' '+item - if line: - lines.append(line) - return lines - -def join_justified(left, right, width=72): - count = max(len(left), len(right)) - left = left + ['']*(count-len(left)) - right = right + ['']*(count-len(right)) - lines = [] - i = 0 - while True: - l = left[i] - r = right[i] - if len(l)+1+len(r) > width: - left = left + [''] - right = right[:i] + [''] + right[i:] - r = right[i] - count += 1 - lines.append( l + ' ' + r.rjust(width-len(l)-1) ) - i += 1 - if i >= count: - break - return lines - def build_file_urls(doc): if isinstance(doc,Document) and doc.get_state_slug() == "rfc": name = doc.canonical_name() @@ -1069,135 +1034,6 @@ def build_file_urls(doc): return file_urls, found_types -def build_doc_supermeta_block(doc): - items = [] - items.append(f'[Search]') - - file_urls, found_types = build_file_urls(doc) - file_urls = [('txt',url) if label=='plain text' else (label,url) for label,url in file_urls] - - if file_urls: - file_labels = { - 'txt' : 'Plaintext version of this document', - 'xml' : 'XML source for this document', - 'pdf' : 'PDF version of this document', - 'html' : 'HTML version of this document, from XML2RFC', - 'bibtex' : 'BibTex entry for this document', - } - parts=[] - for label,url in file_urls: - if 'htmlized' not in label: - file_label=file_labels.get(label,'') - title_attribute = f' title="{file_label}"' if file_label else '' - partstring = f'{label}' - parts.append(partstring) - items.append('[' + '|'.join(parts) + ']') - - items.append(f'[Tracker]') - if doc.group.acronym != 'none': - items.append(f'[WG]') - items.append(f'[Email]') - if doc.rev != "00": - items.append(f'[Diff1]') - items.append(f'[Diff2]') - items.append(f'[Nits]') - - return ' '.join(items) - -def build_doc_meta_block(doc, path): - def add_markup(path, doc, lines): - is_hst = doc.is_dochistory() - rev = doc.rev - if is_hst: - doc = doc.doc - name = doc.name - rfcnum = doc.rfc_number() - errata_url = settings.RFC_EDITOR_ERRATA_URL.format(rfc_number=rfcnum) if not is_hst else "" - ipr_url = "%s?submit=draft&id=%s" % (urlreverse('ietf.ipr.views.search'), name) - for i, line in enumerate(lines): - # add draft links - line = re.sub(r'\b(draft-[-a-z0-9]+)\b', r'\g<1>'%(path, ), line) - # add rfcXXXX to RFC links - line = re.sub(r' (rfc[0-9]+)\b', r' \g<1>'%(path, ), line) - # add XXXX to RFC links - line = re.sub(r' ([0-9]{3,5})\b', r' \g<1>'%(path, ), line) - # add draft revision links - line = re.sub(r' ([0-9]{2})\b', r' \g<1>'%(path, name, ), line) - if rfcnum: - # add errata link - line = re.sub(r'Errata exist', r'Errata exist'%(errata_url, ), line) - if is_hst or not rfcnum: - # make current draft rev bold - line = re.sub(r'>(%s)<'%rev, r'>\g<1><', line) - line = re.sub(r'IPR declarations', r'IPR declarations'%(ipr_url, ), line) - line = line.replace(r'[txt]', r'[txt]' % doc.get_href()) - lines[i] = line - return lines - # - now = timezone.now() - draft_state = doc.get_state('draft') - block = '' - meta = {} - if doc.type_id == 'draft': - revisions = [] - ipr = doc.related_ipr() - if ipr: - meta['ipr'] = [ "IPR declarations" ] - if doc.is_rfc() and not doc.is_dochistory(): - if not doc.name.startswith('rfc'): - meta['from'] = [ "%s-%s"%(doc.name, doc.rev) ] - meta['errata'] = [ "Errata exist" ] if doc.tags.filter(slug='errata').exists() else [] - - meta['obsoletedby'] = [ document.rfc_number() for alias in doc.related_that('obs') for document in alias.docs.all() ] - meta['obsoletedby'].sort() - meta['updatedby'] = [ document.rfc_number() for alias in doc.related_that('updates') for document in alias.docs.all() ] - meta['updatedby'].sort() - meta['stdstatus'] = [ doc.std_level.name ] - else: - dd = doc.doc if doc.is_dochistory() else doc - revisions += [ '(%s)%s'%(d.name, ' '*(2-((len(d.name)-1)%3))) for d in dd.replaces() ] - revisions += doc.revisions() - if doc.is_dochistory() and doc.doc.is_rfc(): - revisions += [ doc.doc.canonical_name() ] - else: - revisions += [ d.name for d in doc.replaced_by() ] - meta['versions'] = revisions - if not doc.is_dochistory and draft_state.slug == 'active' and now > doc.expires: - # Active past expiration date - meta['active'] = [ 'Document is active' ] - meta['state' ] = [ doc.friendly_state() ] - intended_std = doc.intended_std_level if doc.intended_std_level else None - if intended_std: - if intended_std.slug in ['ps', 'ds', 'std']: - meta['stdstatus'] = [ "Standards Track" ] - else: - meta['stdstatus'] = [ intended_std.name ] - elif doc.type_id == 'charter': - meta['versions'] = doc.revisions() - # - # Add markup to items that needs it. - if 'versions' in meta: - meta['versions'] = label_wrap('Versions', meta['versions'], joiner="") - for label in ['Obsoleted by', 'Updated by', 'From' ]: - item = label.replace(' ','').lower() - if item in meta and meta[item]: - meta[item] = label_wrap(label, meta[item]) - # - left = [] - right = [] - #right = [ '[txt]'] - for item in [ 'from', 'versions', 'obsoletedby', 'updatedby', ]: - if item in meta and meta[item]: - left += meta[item] - for item in ['stdstatus', 'active', 'state', 'ipr', 'errata', ]: - if item in meta and meta[item]: - right += meta[item] - lines = join_justified(left, right) - block = '\n'.join(add_markup(path, doc, lines)) - # - return block - - def augment_docs_and_user_with_user_info(docs, user): """Add attribute to each document with whether the document is tracked or has a review wish by the user or not, and the review teams the user is on.""" diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index bdf3b6c1a..4c7d21645 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -49,6 +49,7 @@ from django.template.loader import render_to_string from django.urls import reverse as urlreverse from django.conf import settings from django import forms +from django.contrib.staticfiles import finders import debug # pyflakes:ignore @@ -61,9 +62,9 @@ from ietf.doc.utils import (add_links_in_new_revision_events, augment_events_wit can_adopt_draft, can_unadopt_draft, get_chartering_type, get_tags_for_stream_id, needed_ballot_positions, nice_consensus, prettify_std_name, update_telechat, has_same_ballot, get_initial_notify, make_notify_changed_event, make_rev_history, default_consensus, - add_events_message_info, get_unicode_document_content, build_doc_meta_block, + add_events_message_info, get_unicode_document_content, augment_docs_and_user_with_user_info, irsg_needed_ballot_positions, add_action_holder_change_event, - build_doc_supermeta_block, build_file_urls, update_documentauthors, fuzzy_find_documents, + build_file_urls, update_documentauthors, fuzzy_find_documents, bibxml_for_draft) from ietf.doc.utils_bofreq import bofreq_editors, bofreq_responsible from ietf.group.models import Role, Group @@ -140,12 +141,12 @@ def interesting_doc_relations(doc): return interesting_relations_that, interesting_relations_that_doc -def document_main(request, name, rev=None): +def document_main(request, name, rev=None, document_html=False): doc = get_object_or_404(Document.objects.select_related(), docalias__name=name) # take care of possible redirections aliases = DocAlias.objects.filter(docs=doc).values_list("name", flat=True) - if rev==None and doc.type_id == "draft" and not name.startswith("rfc"): + if document_html is False and rev==None and doc.type_id == "draft" and not name.startswith("rfc"): for a in aliases: if a.startswith("rfc"): return redirect("ietf.doc.views_doc.document_main", name=a) @@ -169,7 +170,7 @@ def document_main(request, name, rev=None): doc = h break - if not snapshot: + if not snapshot and document_html is False: return redirect('ietf.doc.views_doc.document_main', name=name) if doc.type_id == "charter": @@ -184,7 +185,6 @@ def document_main(request, name, rev=None): top = render_document_top(request, doc, "status", name) - telechat = doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat") if telechat and (not telechat.telechat_date or telechat.telechat_date < date_today(settings.TIME_ZONE)): telechat = None @@ -446,8 +446,22 @@ def document_main(request, name, rev=None): else: stream_desc = "(None)" - return render(request, "doc/document_draft.html", + html = None + js = None + css = None + if document_html: + html = doc.html_body() + if request.COOKIES.get("pagedeps") == "inline": + js = Path(finders.find("ietf/js/document_html.js")).read_text() + css = Path(finders.find("ietf/css/document_html_inline.css")).read_text() + if html: + css += Path(finders.find("ietf/css/document_html_txt.css")).read_text() + return render(request, "doc/document_draft.html" if document_html is False else "doc/document_html.html", dict(doc=doc, + document_html=document_html, + css=css, + js=js, + html=html, group=group, top=top, name=name, @@ -787,7 +801,6 @@ def document_raw_id(request, name, rev=None, ext=None): except: raise Http404 - def document_html(request, name, rev=None): found = fuzzy_find_documents(name, rev) num_found = found.documents.count() @@ -811,30 +824,7 @@ def document_html(request, name, rev=None): if not os.path.exists(doc.get_file_name()): raise Http404("File not found: %s" % doc.get_file_name()) - if doc.type_id in ['draft',]: - doc.supermeta = build_doc_supermeta_block(doc) - doc.meta = build_doc_meta_block(doc, settings.HTMLIZER_URL_PREFIX) - - doccolor = 'bgwhite' # Unknown - if doc.type_id=='draft': - if doc.is_rfc(): - if doc.related_that('obs'): - doccolor = 'bgbrown' - else: - doccolor = { - 'ps' : 'bgblue', - 'exp' : 'bgyellow', - 'inf' : 'bgorange', - 'ds' : 'bgcyan', - 'hist' : 'bggrey', - 'std' : 'bggreen', - 'bcp' : 'bgmagenta', - 'unkn' : 'bgwhite', - }.get(doc.std_level_id, 'bgwhite') - else: - doccolor = 'bgred' # Draft - - return render(request, "doc/document_html.html", {"doc":doc, "doccolor":doccolor }) + return document_main(request, name, rev=rev, document_html=True) def document_pdfized(request, name, rev=None, ext=None): diff --git a/ietf/static/css/document_html.scss b/ietf/static/css/document_html.scss new file mode 100644 index 000000000..f23f466b3 --- /dev/null +++ b/ietf/static/css/document_html.scss @@ -0,0 +1,316 @@ +@use "sass:map"; + +// FIXME: It's not clear why these three variables remain unset by bs5, but just +// set them to placeholder values so the CSS embedded in the HTML validates. +$btn-font-family: inherit !default; +$nav-link-font-weight: inherit !default; +$tooltip-margin: inherit !default; + +@import "bootstrap/scss/functions"; +@import "bootstrap/scss/variables"; +@import "bootstrap/scss/maps"; +@import "bootstrap/scss/mixins"; +@import "bootstrap/scss/utilities"; +@import "bootstrap/scss/root"; + +// Layout & components +@import "bootstrap/scss/reboot"; +@import "bootstrap/scss/type"; +// @import "bootstrap/scss/images"; +@import "bootstrap/scss/containers"; +@import "bootstrap/scss/grid"; +// @import "bootstrap/scss/tables"; +@import "bootstrap/scss/forms"; +@import "bootstrap/scss/buttons"; +@import "bootstrap/scss/transitions"; +// @import "bootstrap/scss/dropdown"; +@import "bootstrap/scss/button-group"; +@import "bootstrap/scss/nav"; +@import "bootstrap/scss/navbar"; +// @import "bootstrap/scss/card"; +// @import "bootstrap/scss/accordion"; +// @import "bootstrap/scss/breadcrumb"; +@import "bootstrap/scss/pagination"; +@import "bootstrap/scss/badge"; +@import "bootstrap/scss/alert"; +// @import "bootstrap/scss/progress"; +// @import "bootstrap/scss/list-group"; +// @import "bootstrap/scss/close"; +// @import "bootstrap/scss/toasts"; +// @import "bootstrap/scss/modal"; +@import "bootstrap/scss/tooltip"; +// @import "bootstrap/scss/popover"; +// @import "bootstrap/scss/carousel"; +// @import "bootstrap/scss/spinners"; +// @import "bootstrap/scss/offcanvas"; +// @import "bootstrap/scss/placeholders"; + +// Helpers +@import "bootstrap/scss/helpers"; + +// Utilities +@import "bootstrap/scss/utilities/api"; + +:root { + --doc-ptsize-max: 16pt; +} + +.overscroll-none { + overscroll-behavior: none; +} + +.no-scrollbar { + scrollbar-width: none; +} + +.sidebar-toggle[aria-expanded="true"] { + display: none; +} + +.sidebar-toggle[aria-expanded="false"] { + display: inherit; +} + +@media screen { + @include media-breakpoint-down(md) { + body { + padding-top: 60px; + } + + html { + scroll-padding-top: 60px; + } + } + + @include media-breakpoint-down(sm) { + body { + padding-top: 70px; + } + + html { + scroll-padding-top: 70px; + } + } +} + +.rfcmarkup, +.rfchtml { + font-family: var(--bs-font-monospace); + + caption { + padding: 0; + color: var(--bs-body-color); + } + + code { + font-size: 1em; + color: var(--bs-body-color); + } + + @media screen { + @include media-breakpoint-only(xs) { + font-size: min(7pt, var(--doc-ptsize-max)); + } + + @include media-breakpoint-up(sm) { + font-size: min(9.5pt, var(--doc-ptsize-max)); + } + + @include media-breakpoint-up(md) { + font-size: min(9.5pt, var(--doc-ptsize-max)); + } + + @include media-breakpoint-up(lg) { + font-size: min(11pt, var(--doc-ptsize-max)); + } + + @include media-breakpoint-up(xl) { + font-size: min(13pt, var(--doc-ptsize-max)); + } + + @include media-breakpoint-up(xxl) { + font-size: min(16pt, var(--doc-ptsize-max)); + } + + .grey, + hr { + opacity: $hr-opacity; + } + } + + h1, + h2, + h3, + h4, + h5, + h6 { + font-weight: bold; + font-size: 1em; + } + + pre, + code { + font-size: 1em; + } + + pre { + width: 72ch; + margin: 0; + padding: 0; + } + + .bcp14 { + font-weight: bold; + // color: $gray-700; + } +} + +.rfcmarkup { + + h1, + h2, + h3, + h4, + h5, + h6 { + white-space: pre; + display: inline; + } +} + +tbody.meta tr { + + td:first-child, + th:first-child, + td.edit { + display: none; + } +} + +.sidebar { + height: 100vh; + + .toplink, + #name-table-of-contents { + display: none; + } + + th, + td { + display: block; + padding: 0; + } + + td { + margin-bottom: map.get($spacers, 3); + } +} + +// Add some padding when there are multiple buttons in a line that can wrap +.buttonlist .btn { + margin-bottom: map.get($spacers, 1); +} + +// Make revision numbers pagination items fixed-width +.revision-list { + .page-item { + width: 2.2rem; + } + + .page-item.rfc { + width: 6.6rem; + } +} + +#docinfo { + max-height: 70vh; + z-index: -1; +} + + +.badge-obs { + color: white; + background-color: $orange-800; +} + +.badge-ps { + color: black; + background-color: $blue-300; +} + +.badge-exp { + color: black; + background-color: $yellow-200; +} + +.badge-inf { + color: white; + background-color: $orange; +} + +.badge-ds { + color: black; + background-color: $cyan-200; +} + +.badge-hist { + color: white; + background-color: $gray-700; +} + +.badge-std { + color: black; + background-color: $teal-200; +} + +.badge-bcp { + color: white; + background-color: $pink-500; +} + +.badge-unkn { + color: black; + background-color: $gray-300; +} + +.badge-draft { + color: white; + background-color: $danger; +} + +#toc-nav { + width: inherit; + overscroll-behavior-y: none; // Prevent overscrolling from scrolling the main content +} + + +@media print { + @page { + size: letter; + margin: .75in; + } + + body { + margin: 0; + padding: 0; + font-size: 10pt; + } + + pre { + page-break-inside: avoid; + } + + a:link, + a:visited { + // color: inherit; + // text-decoration: none; + } + + .newpage { + page-break-before: always !important; + } + + .noprint { + display: none; + } +} diff --git a/ietf/static/css/document_html_inline.scss b/ietf/static/css/document_html_inline.scss new file mode 100644 index 000000000..a75753438 --- /dev/null +++ b/ietf/static/css/document_html_inline.scss @@ -0,0 +1,6 @@ +@import "document_html"; + +// Make the bootstrap icons available via data-url. +$bootstrap-icons-font-src: url(data-url:npm:bootstrap-icons/font/fonts/bootstrap-icons.woff2) format("woff2"), +url(data-url:npm:bootstrap-icons/font/fonts/bootstrap-icons.woff) format("woff"); +@import "bootstrap-icons/font/bootstrap-icons"; diff --git a/ietf/static/css/document_html_referenced.scss b/ietf/static/css/document_html_referenced.scss new file mode 100644 index 000000000..534298940 --- /dev/null +++ b/ietf/static/css/document_html_referenced.scss @@ -0,0 +1,6 @@ +@import "document_html"; + +// Make the bootstrap icons available. +$bootstrap-icons-font-src: url("npm:bootstrap-icons/font/fonts/bootstrap-icons.woff2") format("woff2"), +url("npm:bootstrap-icons/font/fonts/bootstrap-icons.woff") format("woff"); +@import "bootstrap-icons/font/bootstrap-icons"; diff --git a/ietf/static/css/document_html_txt.scss b/ietf/static/css/document_html_txt.scss new file mode 100644 index 000000000..1f9ef0ad9 --- /dev/null +++ b/ietf/static/css/document_html_txt.scss @@ -0,0 +1,376 @@ +:root { + --line: 1.2em; + --block: 0 0 0 3ch; + --paragraph: var(--line) 0 var(--line) 3ch; +} + +// WeasyPrint can't handle CSS variables in multi-attribute properties, so work +// around that +// https://github.com/Kozea/WeasyPrint/issues/1219 + +@mixin margin-paragraph { + margin-top: var(--line); + margin-right: 0; + margin-bottom: var(--line); + margin-left: 3ch; +} + +@mixin margin-line { + margin-top: var(--line); + margin-right: 0; + margin-bottom: var(--line); + margin-left: 0; +} + +@mixin margin-block { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 3ch; +} + +.rfchtml { +// body { +// color: black; +// font-family: monospace; +// font-size: 1em; + line-height: var(--line); + width: 72ch; + + // margin: var(--line) 3ch; + margin-top: var(--line); + margin-right: 3ch; + margin-bottom: var(--line); + margin-left: 3ch; + +h1, h2, h3, h4, h5 { + font-weight: bold; + font-size: inherit; + line-height: inherit; + // margin: var(--line) 0; + @include margin-line; +} +.section-number { + margin-right: 1ch; +} +p { + // margin: var(--paragraph); + @include margin-paragraph; +} +aside, ol, dl { + // margin: var(--block); + @include margin-block; +} +figure { + margin: 0; +} +blockquote { + // margin: var(--paragraph); + @include margin-paragraph; + border-left: 2px solid darkgrey; +} + +/* Header junk */ +#external-metadata { + display: none !important; /* metadata.min.js is evil because it produces unstyleable goop */ +} +#identifiers dt:is(.label-stream, .label-rfc, .label-std, .label-bcp, .label-internet-draft, + .label-workgroup, .label-intended-status, .label-obsoletes, .label-updates, + .label-published, .label-expires, .label-category, .label-issn, + .label-authors), .ears { + display: none; +} +#identifiers { + margin: 0; + display: grid; + grid-template-columns: 47ch 24ch; + grid-auto-rows: auto; + gap: 0 1ch; +} +#identifiers dt { + margin: 0 1ch 0 0; + float: revert; + display: inline-block; +} +#identifiers dd { + grid-column: 1; + margin: 0; + width: 47ch; + /* HAXX: this gets around the lack of text-content-trim support */ + display: flex; + flex-wrap: wrap; +} +#identifiers dd::before { + margin: 0 1ch 0 0; +} +#identifiers dd.rfc::before { + content: "Request for Comments:"; +} +#identifiers dd.std::before { + content: "STD:"; +} +#identifiers dd.bcp::before { + content: "BCP:"; +} +#identifiers dd.internet-draft::before { + content: "Internet-Draft:"; +} +#identifiers dd.workgroup::before { + content: "Workgroup:"; +} +#identifiers dd.intended-status::before { + content: "Intended Status:"; +} +#identifiers dd.obsoletes::before { + content: "Obsoletes:"; + margin: 0 0 0 -10ch; +} +#identifiers dd.obsoletes { + padding-left: 10ch; + width: 37ch; +} +#identifiers dd.updates::before { + content: "Updates:"; + margin: 0 0 0 -8ch; +} +#identifiers dd.updates { + padding-left: 8ch; + width: 39ch; +} +#identifiers dd:is(.updates, .obsoletes) a { + margin: 0 0 0 1ch; +} +#identifiers dd:is(.updates, .obsoletes) a:last-of-type { + margin: 0 1ch; +} +#identifiers dd.published::before { + content: "Published:"; +} +#identifiers dd.expires::before { + content: "Expires:"; +} +#identifiers dd.category::before { + content: "Category:"; +} +#identifiers dd.issn::before { + content: "ISSN:"; +} +#identifiers dd.authors { + grid-area: 1 / 2 / 100 / 3; + width: 24ch; + text-align: right; + display: block; +} + +#title { + clear: left; + text-align: center; + margin-top: 2em; +} +#rfcnum { + display: none; +} +.toplink { + display: none; +} +nav.toc ul { + list-style: none; + margin: 0; + padding: 0; +} +nav.toc ul > li { + padding-left: 2ch; +} +nav.toc > ul > li { + padding-left: 3ch; +} +nav.toc ul > li > p { + margin: 0; +} + +/* Lists */ +ol, ul { + padding: 0; +} +ol { + margin: 0 0 0 6ch; /* todo: deal with lists that have >= 10 items */ +} +ol ol, ul ol { + margin: 0 0 0 3ch; +} +ul { + margin: 0 0 0 4ch; + list-style-type: '*'; +} +ul ul { + list-style-type: '-'; +} +ul ul, ol ul { + margin-left: 1ch; +} +ul ul ul { + list-style-type: 'o'; +} +li { + // margin: var(--line) 0; + @include margin-line; + padding: 0 0 0 2ch; +} +.compact li { + margin: 0; +} +li p:first-child, dd p:first-child { + margin: 0; +} +dt { + float: left; + clear: left; + margin: 0 2ch 0 0; + break-after: avoid; +} +dd { + // margin: var(--paragraph); + @include margin-paragraph; + break-before: avoid; +} +dl.compact dt, dl.compact dd { + margin-top: 0; + margin-bottom: 0; +} +dl.references dt { + margin-right: 1ch; +} +dl.references dd { + margin-left: 11ch; +} +dd.break { + display: none; +} + +/* Figures, tables */ +pre { + // margin: var(--line) 0; + @include margin-line; +} +div.artwork, div.sourcecode { + display: flex; + flex-wrap: nowrap; + align-items: end; +} +div.artwork.alignCenter, div.sourcecode.alignCenter { + justify-content: center; +} +div.artwork.alignRight, div.sourcecode.alignRight { + justify-content: end; +} +div.artwork::before, div.sourcecode::before { + flex: 0 1 3ch; + content: ""; +} +div.artwork.alignRight::before, div.sourcecode.alignRight::before { + flex-grow: 1; +} +div.artwork pre, div.sourcecode pre { + flex: 0 0 content; + margin: 0; + max-width: 72ch; + overflow: auto; +} +div.artwork .pilcrow, div.sourcecode .pilcrow { + flex: 0 0 1ch; +} +figcaption, table caption { + text-align: center; + margin-top: var(--line); +} +table { + --half-line: calc(var(--line) / 2 - 1px); + caption-side: bottom; + // margin: var(--line) 0 var(--half-line) 3ch; + margin-top: var(--line); + margin-right: 0; + margin-bottom: var(--half-line); + margin-left: 3ch; + border-collapse: collapse; +} +table.center { + margin-left: auto; /* todo: add 3ch */ + margin-right: auto; +} +table caption { + margin-top: calc(var(--half-line) + var(--line)); +} +thead, tfoot { + border-top-style: double; + border-bottom-style: double; +} +td, th { + border: 1px solid black; + // padding: var(--half-line) 1ch; + padding-top: var(--half-line); + padding-right: 1ch; + padding-bottom: var(--half-line); + padding-left: 1ch; +} +.text-left { + text-align: left; +} +.text-center { + text-align: center; +} +.text-right { + text-align: right; +} + +/* Links */ +a.selfRef, a.pilcrow { + color: black; + text-decoration: none; +} +a.relref, a.xref { + hyphens: none; +} +a.relref, a.xref.cite { + white-space: nowrap; +} +.pilcrow { + display: inline-block; + margin-right: -1ch; + opacity: 0.01; + text-decoration: none; +} +:hover > .pilcrow { + opacity: 0.2; +} +* > .pilcrow[href]:hover { + opacity: 0.6; +} + +/* sup, sub */ +sup, sub { + line-height: 1.1; +} + +/* Authors */ +address { + font-style: normal; + // margin: 2em 0 var(--line) 3ch; + margin-top: 2em; + margin-right: 0; + margin-bottom: var(--line); + margin-left: 3ch; +} +h2 + address { + margin-top: 1em; +} +address .tel, address .email { + // margin: var(--line) 0 0; + margin-top: var(--line); + margin-right: 0; + margin-bottom: 0; + margin-left: 0; +} +address .tel + .email { + margin: 0; +} +} diff --git a/ietf/static/css/ietf.scss b/ietf/static/css/ietf.scss index 86b71f154..9cfb610b7 100644 --- a/ietf/static/css/ietf.scss +++ b/ietf/static/css/ietf.scss @@ -168,8 +168,9 @@ table tbody.meta { } } -// Try and hyphenate table headings -th { +// Try and hyphenate table headings and other things +th, +.hyphenate { hyphens: auto; } @@ -208,6 +209,17 @@ th { max-width: 300px; } +// Make revision numbers pagination items fixed-width +.revision-list { + .page-item { + width: 2.2rem; + } + + .page-item.rfc { + width: 6.6rem; + } +} + // Style the photo cards .photo { width: 12em; diff --git a/ietf/static/images/irtf-logo.svg b/ietf/static/images/irtf-logo.svg index ad339fe2b..be64890b2 100644 --- a/ietf/static/images/irtf-logo.svg +++ b/ietf/static/images/irtf-logo.svg @@ -1 +1,76 @@ - \ No newline at end of file + + diff --git a/ietf/static/js/document_html.js b/ietf/static/js/document_html.js new file mode 100644 index 000000000..2d0882df5 --- /dev/null +++ b/ietf/static/js/document_html.js @@ -0,0 +1,86 @@ +import { + Tooltip as Tooltip, + // Button as Button, + // Collapse as Collapse, + // ScrollSpy as ScrollSpy, + Tab as Tab +} from "bootstrap"; + +import Cookies from "js-cookie"; +import { populate_nav } from "./nav.js"; + +const cookies = Cookies.withAttributes({ sameSite: "strict" }); + +document.addEventListener("DOMContentLoaded", function (event) { + // handle point size slider + const cookie = "doc-ptsize-max"; + + function change_ptsize(ptsize) { + document.documentElement.style.setProperty(`--${cookie}`, + `${ptsize}pt`); + cookies.set(cookie, ptsize); + } + + document.getElementById("ptsize") + .oninput = function () { change_ptsize(this.value) }; + + const ptsize = cookies.get(cookie); + change_ptsize(ptsize ? Math.min(Math.max(7, ptsize), 16) : 12); + + // Use the Bootstrap tooltip plugin for all elements with a title attribute + const tt_triggers = document.querySelectorAll( + "[title]:not([title=''])"); + [...tt_triggers].map(tt_el => { + const tooltip = Tooltip.getOrCreateInstance(tt_el); + tt_el.addEventListener("click", el => { + tooltip.hide(); + tt_el.blur(); + }); + }); + + // Rewrite ids and hrefs to not contains dots (bug in bs5.2 scrollspy) + // See https://github.com/twbs/bootstrap/issues/34381 + // TODO: check if this can be removed when bs5 is updated + const ids = document.querySelectorAll( + "#content [id^=section-], #content [id^=appendix-]"); + [...ids].map(id_el => id_el.id = id_el.id.replaceAll(/\./g, "-")); + const hrefs = document.querySelectorAll( + "#content [href*='#section-'], #content [href*='#appendix-']" + ); + [...hrefs].map(id_el => { + const href = new URL(id_el.href); + href.hash = href.hash.replaceAll(/\./g, "-"); + id_el.href = href.href; + }); + + // Set up a nav pane + const toc_pane = document.getElementById("toc-nav"); + populate_nav(toc_pane, + `#content h2, #content h3, #content h4, #content h5, #content h6 + #content .h1, #content .h2, #content .h3, #content .h4, #content .h5, #content .h6`, + ["py-0"]); + + // activate pref buttons selected by pref cookies + document.querySelectorAll(".btn-check") + .forEach(btn => { + const id = btn.id.replace("-radio", ""); + if (cookies.get(btn.name) == id) { + btn.checked = true; + } + btn.addEventListener("click", el => { + cookies.set(btn.name, id); + window.location.reload(); + }); + }); + + // activate tab selected in prefs + let defpane; + try { + defpane = Tab.getOrCreateInstance( + `#${cookies.get("deftab")}-tab`); + } catch (err) { + defpane = Tab.getOrCreateInstance("#docinfo-tab"); + }; + defpane.show(); + document.activeElement.blur(); +}); diff --git a/ietf/static/js/ietf.js b/ietf/static/js/ietf.js index c30fe6fcb..17165bbfb 100644 --- a/ietf/static/js/ietf.js +++ b/ietf/static/js/ietf.js @@ -24,7 +24,7 @@ if (!process.env.BUILD_DEPLOY) { import Cookies from "js-cookie"; -import debounce from "lodash/debounce"; +import { populate_nav } from "./nav.js"; // setup CSRF protection using jQuery function csrfSafeMethod(method) { @@ -154,9 +154,9 @@ $(document) $(function () { const contentElement = $('#content.ietf-auto-nav'); if (contentElement.length > 0) { + const heading_selector = "h2:not([style='display:none']):not(.navskip), h3:not([style='display:none']):not(.navskip), h4:not([style='display:none']):not(.navskip), h5:not([style='display:none']):not(.navskip), h6:not([style='display:none']):not(.navskip), .nav-heading:not([style='display:none']):not(.navskip)"; const headings = contentElement - .find("h1:visible, h2:visible, h3:visible, h4:visible, h5:visible, h6:visible, .nav-heading:visible") - .not(".navskip"); + .find(heading_selector); const contents = (headings.length > 0) && ($(headings) @@ -178,8 +178,6 @@ $(function () { if (pageTooTall || haveExtraNav) { // console.log("Enabling nav."); - let n = 0; - let last_level; contentElement .attr("data-bs-offset", 0) @@ -197,48 +195,7 @@ $(function () { .children() .last(); - contentElement - .find("h1:visible, h2:visible, h3:visible, h4:visible, h5:visible, h6:visible, .nav-heading:visible") - .not(".navskip") - .each(function () { - // Some headings have line breaks in them - only use first line in that case. - const frag = $(this) - .html() - .split("
$(x) - .text()) - .join(" "); - - if (text === undefined || text === "") { - // Nothing to do for empty headings. - return; - } - let id = $(this) - .attr("id"); - - if (id === undefined) { - id = `autoid-${++n}`; - $(this) - .attr("id", id); - } - - const level = parseInt(this.nodeName.substring(1)) - 1; - if (!last_level) { - last_level = level; - } - - if (level > last_level) { - last_level = level; - } else - while (level < last_level) { - last_level--; - } - - $(nav) - .append(`${text}`); - }); + populate_nav(nav[0], heading_selector); if (haveExtraNav) { $('#righthand-panel').append(''); @@ -246,18 +203,6 @@ $(function () { extraNav.remove(); } - $(document) - // Chrome apparently wants this debounced to something >10ms, - // otherwise the main view doesn't scroll? - .on("scroll", debounce(function () { - const item = $('#righthand-nav') - .find(".active") - .last(); - if (item.length) { - item[0].scrollIntoView({ block: "center", behavior: "smooth" }); - } - }, 100)); - // offset the scrollspy to account for the menu bar const contentOffset = contentElement ? contentElement.offset().top : 0; diff --git a/ietf/static/js/nav.js b/ietf/static/js/nav.js new file mode 100644 index 000000000..06b82f80d --- /dev/null +++ b/ietf/static/js/nav.js @@ -0,0 +1,100 @@ +import debounce from "lodash/debounce"; + +function make_nav() { + const nav = document.createElement("nav"); + nav.classList.add("nav-pills", "ps-3", "flex-column"); + return nav; +} + +function get_level(el) { + let h; + if (el.tagName.match(/^h\d/i)) { + h = el.tagName + } else { + el.classList.forEach(cl => { + if (cl.match(/^h\d/i)) { + h = cl; + return; + } + }); + } + return h.charAt(h.length - 1); +} + +export function populate_nav(nav, heading_selector, classes) { + // Extract section headings from document + const headings = document.querySelectorAll(heading_selector); + const min_level = Math.min(...Array.from(headings) + .map(get_level)); + + let nav_stack = [nav]; + let cur_level = 0; + let n = 0; + + headings.forEach(el => { + const level = get_level(el) - min_level; + + if (level < cur_level) { + while (level < cur_level) { + let nav = nav_stack.pop(); + cur_level--; + nav_stack[level].appendChild(nav); + } + } else { + while (level > cur_level) { + nav_stack.push(make_nav()); + cur_level++; + } + } + + const link = document.createElement("a"); + link.classList.add("nav-link", "ps-1", "d-flex", "hyphenate", + classes); + + if (!el.id) { + el.id = `autoid-${++n}`; + } + link.href = `#${el.id}`; + + const words = el.innerText.split(/\s+/); + let nr = ""; + if (words[0].includes(".")) { + nr = words.shift(); + } else if (words.length > 1 && words[1].includes(".")) { + nr = words.shift() + " " + words.shift(); + nr = nr.replace(/\s*Appendix\s*/, ""); + } + + if (nr) { + const number = document.createElement("div"); + number.classList.add("pe-1"); + number.textContent = nr; + link.appendChild(number); + } + + const text = document.createElement("div"); + text.classList.add("text-break"); + text.textContent = words.join(" "); + link.appendChild(text); + + nav_stack[level].appendChild(link); + }); + + for (var i = nav_stack.length - 1; i > 0; i--) { + nav_stack[i - 1].appendChild(nav_stack[i]); + } + + // Chrome apparently wants this debounced to something >10ms, + // otherwise the main view doesn't scroll? + document.addEventListener("scroll", debounce(function () { + const items = nav.querySelectorAll(".active"); + const item = [...items].pop(); + console.log(item); + if (item) { + item.scrollIntoView({ + block: "center", + behavior: "smooth" + }); + } + }, 100)); +} diff --git a/ietf/templates/doc/document_draft.html b/ietf/templates/doc/document_draft.html index 0bb597b60..f763159fc 100644 --- a/ietf/templates/doc/document_draft.html +++ b/ietf/templates/doc/document_draft.html @@ -26,7 +26,7 @@ {% block content %} {% origin %} {{ top|safe }} - {% include "doc/revisions_list.html" %} + {% include "doc/revisions_list.html" with document_html=document_html %} {% if doc.rev != latest_rev %}The information below is for an old version of the document.@@ -38,363 +38,7 @@ {% endif %} {% endif %}
Document | -Type | -- |
- {% if doc.get_state_slug == "rfc" and not snapshot %}
- RFC - {{ doc.std_level }}
- {% if published %}
- ({{ doc.pub_date|date:"F Y" }})
- {% else %}
- (Publication date unknown)
- {% endif %}
- {% if has_verified_errata %}
-
- Errata
-
- {% elif has_errata %}
-
- Errata
-
- {% endif %}
- {% if obsoleted_by %} Obsoleted by {{ obsoleted_by|urlize_related_source_list|join:", " }} {% endif %}
- {% if updated_by %}Updated by {{ updated_by|urlize_related_source_list|join:", " }} {% endif %}
- {% if obsoletes %}Obsoletes {{ obsoletes|urlize_related_target_list|join:", " }} {% endif %}
- {% if updates %}Updates {{ updates|urlize_related_target_list|join:", " }} {% endif %}
- {% if status_changes %}
- Status changed by {{ status_changes|urlize_related_source_list|join:", " }}
- {% endif %}
- {% if proposed_status_changes %}
- Proposed status changed by {{ proposed_status_changes|urlize_related_source_list|join:", " }}
- {% endif %}
- {% if rfc_aliases %}Also known as {{ rfc_aliases|join:", "|urlize_ietf_docs }} {% endif %}
- {% if draft_name %}
-
- Was
- {{ draft_name }}
- {% if submission %}({{ submission|safe }}){% endif %}
-
- {% endif %}
- {% else %}
- {% if snapshot and doc.doc.get_state_slug == 'rfc' %}
- This is an older version of an Internet-Draft that was ultimately published as an RFC.
- {% elif snapshot and doc.rev != latest_rev %}
- This is an older version of an Internet-Draft whose latest revision is {{ doc.doc.get_state }}
- {% else %}
- {% if snapshot and doc.rev == latest_rev %}{{ doc.doc.get_state }}{% else %}{{ doc.get_state }}{% endif %} Internet-Draft
- {% if submission %}({{ submission|safe }}){% endif %}
- {% if resurrected_by %}- resurrect requested by {{ resurrected_by }}{% endif %}
- {% endif %}
- {% endif %}
- |
-
---|---|---|---|
- | Author{{ doc.authors|pluralize }} | -- {% if can_edit_authors %} - Edit - {% endif %} - | -- {# Implementation that uses the current primary email for each author #} - {% for author in doc.authors %} - {% person_link author %}{% if not forloop.last %},{% endif %} - {% endfor %} - | -
- | Last updated | -- | - {{ doc.time|date:"Y-m-d" }} - {% if latest_revision and latest_revision.time|date:"Y-m-d" != doc.time|date:"Y-m-d" %} - (Latest revision {{ latest_revision.time|date:"Y-m-d" }}) - {% endif %} - | -
- | Replaces | -- {% if can_edit_stream_info and not snapshot %} - Edit - {% endif %} - | -- {% if replaces %} - {{ replaces|urlize_related_target_list|join:", " }} - {% else %} - (None) - {% endif %} - | -
- | - Replaced by - | -- | -- {{ replaced_by|urlize_related_source_list|join:", " }} - | -
- | - Possibly Replaces - | -- {% if can_edit_replaces and not snapshot %} - - Edit - - {% endif %} - | -- {{ possibly_replaces|urlize_related_target_list|join:", " }} - | -
- | - Possibly Replaced By - | -- {% if can_edit_replaces and not snapshot %} - {% comment %}Edit{% endcomment %} - {% endif %} - | -- {{ possibly_replaced_by|urlize_related_source_list|join:", " }} - | -
- | - Stream - | -- {% if can_change_stream and not snapshot %} - - Edit - - {% endif %} - | -- {{ stream_desc }} - | -
- | - Intended RFC status - | -- {% if can_edit_stream_info and not snapshot %} - - Edit - - {% endif %} - | -- {% if doc.intended_std_level %} - {{ doc.intended_std_level }} - {% else %} - - (None) - - {% endif %} - | -
- | - Formats - | -- | -
- {% if doc.get_state_slug != "active" and doc.get_state_slug != "rfc" %}
-
- Expired & archived
-
- {% endif %}
- {% include "doc/document_format_buttons.html" %}
- |
-
- | - {{ check.checker|title }} - | -- | -- {% if check.errors or check.warnings %} - - {{ check.symbol|safe }} - - {% else %} - - {{ check.symbol|safe }} - - {% endif %} - - {{ check.errors }} errors, {{ check.warnings }} warnings - - {% include "doc/yang-check-modal-overlay.html" %} - | -
- | - Reviews - | -- | -
- {% for review_assignment in review_assignments %}
- {% include "doc/review_assignment_summary.html" with current_doc_name=doc.name current_rev=doc.rev %}
- {% endfor %}
- {% if no_review_from_teams %}
- {% for team in no_review_from_teams %}
- {{ team.acronym.upper }}{% if not forloop.last %},{% endif %}
- {% endfor %}
- will not review this version
- {% endif %}
- {% if can_request_review or can_submit_unsolicited_review_for_teams %}
-
- {% if can_request_review %}
-
-
-
- Request review
-
- {% endif %}
- {% if can_submit_unsolicited_review_for_teams|length == 1 %}
-
-
-
- Submit unsolicited review
-
- {% elif can_submit_unsolicited_review_for_teams %}
-
-
-
- Submit unsolicited review
-
- {% endif %}
-
- {% endif %}
- |
-
- | - IETF conflict review - | -- | -- {{ conflict_reviews|join:", "|urlize_ietf_docs }} - | -
- | -- Additional resources - | -- {% if can_edit_stream_info or can_edit_individual %} - - Edit - - {% endif %} - | -
- {% if resources or doc.group and doc.group.list_archive %}
- {% for resource in resources|dictsort:"display_name" %}
- {% if resource.name.type.slug == 'url' or resource.name.type.slug == 'email' %}
-
- {% firstof resource.display_name resource.name.name %}
-
- - {# Maybe make how a resource displays itself a method on the class so templates aren't doing this switching #} - {% else %} - - {% firstof resource.display_name resource.name.name %}: {{ resource.value|escape }} - - - {% endif %} - {% endfor %} - {% if doc.group and doc.group.list_archive %} - {% if doc.group.list_archive|startswith:settings.MAILING_LIST_ARCHIVE_URL %} - - Mailing list discussion - - {% elif doc.group.list_archive|is_valid_url %} - - Mailing list discussion - - {% else %} - {{ doc.group.list_archive|urlencode }} - {% endif %} - {% endif %} - {% endif %} - |
-
diff --git a/ietf/templates/doc/document_format_buttons.html b/ietf/templates/doc/document_format_buttons.html
index 1dcf3008c..efd125766 100644
--- a/ietf/templates/doc/document_format_buttons.html
+++ b/ietf/templates/doc/document_format_buttons.html
@@ -1,7 +1,18 @@
{% if file_urls %}
- |
{% else %}
diff --git a/ietf/templates/doc/document_html.html b/ietf/templates/doc/document_html.html
index 1f0ed51fc..2811a19c2 100644
--- a/ietf/templates/doc/document_html.html
+++ b/ietf/templates/doc/document_html.html
@@ -1,92 +1,276 @@
-{% extends "doc/htmlized_base.html" %}
{# Copyright The IETF Trust 2016, All Rights Reserved #}
+
+{% load analytical %}
{% load origin %}
{% load static %}
-{% load ietf_filters %}
-{% block pagehead %}
-
-
-{% endblock %}
-{% block morecss %}
- .bgwhite { background-color: white; }
- .bgred { background-color: #F44; }
- .bggrey { background-color: #666; }
- .bgbrown { background-color: #840; }
- .bgorange { background-color: #FA0; }
- .bgyellow { background-color: #EE0; }
- .bgmagenta{ background-color: #F4F; }
- .bgblue { background-color: #66F; }
- .bgcyan { background-color: #4DD; }
- .bggreen { background-color: #4F4; }
- .draftcontent { margin-top:1em;}
-{% endblock %}
-{% block title %}
- {% if doc.get_state_slug == "rfc" %}
- RFC {{ doc.rfc_number }} - {{ doc.title }}
- {% else %}
- {{ doc.name }}-{{ doc.rev }}
- {% endif %}
-{% endblock %}
-{% block content %}
-
- {% origin %}
-