/
LuvDyrachyo
/
Java_assignments
Обзор
Документация
Войти
/
LuvDyrachyo
/
Java_assignments
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
java-web-ru/validation/README.html
62 строки
26 KB
@hexlet/cli
submit java-web-ru/validation
13 май 2024, 11:33
13 май 2024, 11:33
b215735
Код
Авторство
О чём код?
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <style>@charset "UTF-8";@import "https://fonts.bunny.net/css?family=Lato:400,900|Roboto+Mono:400,700&display=swap";div.marpit>svg>foreignObject>section{width:1280px;height:720px;box-sizing:border-box;overflow:hidden;position:relative;scroll-snap-align:center center}div.marpit>svg>foreignObject>section:after{bottom:0;content:attr(data-marpit-pagination);padding:inherit;pointer-events:none;position:absolute;right:0}div.marpit>svg>foreignObject>section:not([data-marpit-pagination]):after{display:none}/* Normalization */div.marpit>svg>foreignObject>section :is(h1,marp-h1){font-size:2em;margin:0.67em 0}div.marpit>svg>foreignObject>section video::-webkit-media-controls{will-change:transform}@page{size:1280px 5000px;margin:0}@media print{body,html{background-color:#fff;margin:0;page-break-inside:avoid;break-inside:avoid-page}div.marpit>svg>foreignObject>section{page-break-before:always;break-before:page}div.marpit>svg>foreignObject>section,div.marpit>svg>foreignObject>section *{-webkit-print-color-adjust:exact!important;animation-delay:0s!important;animation-duration:0s!important;color-adjust:exact!important;transition:none!important}div.marpit>svg[data-marpit-svg]{display:block;height:100vh;width:100vw}} /*! * Marp / Marpit Gaia theme. * * @theme gaia * @author Yuki Hattori * * @auto-scaling true * @size 16:9 1280px 720px * @size 4:3 960px 720px */div.marpit>svg>foreignObject>section :is(pre,marp-pre) code.hljs{display:block;overflow-x:auto;padding:1em}div.marpit>svg>foreignObject>section code.hljs{padding:3px 5px}div.marpit>svg>foreignObjec … [Строка слишком длинная. Вы можете скачать файл] /* @theme my-first-theme */div.marpit>svg>foreignObject>section{width:1280px;height:5000px}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div.marpit>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div.marpit>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div.marpit>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=content],div.marpit>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div.marpit>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div.marpit>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div.marpit>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}</style> <div class="marpit"><svg data-marpit-svg="" viewBox="0 0 1280 5000"><foreignObject width="1280" height="5000"><section id="1" data-marpit-fragments="16"> <h2>Валидация</h2> <h3>Ссылки</h3> <ul> <li data-marpit-fragment="1"><a href="https://javalin.io/documentation#context">Методы работы с контекстом</a></li> <li data-marpit-fragment="2"><a href="https://getbootstrap.com/docs/5.1/getting-started/introduction/#css">Подключение стилей Bootstrap</a></li> <li data-marpit-fragment="3">Тег <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea">textarea</a>, который создает в форме многострочное текстовое поле</li> </ul> <h3>src/main/java/exercise/App.java</h3> <p>Реализуйте создание статьи, в которое входит:</p> <ul> <li data-marpit-fragment="4">GET-обработчик <em>/articles/build</em>, который отображает форму</li> <li data-marpit-fragment="5">POST-обработчик <em>/articles</em>, который создает курс</li> </ul> <p>Сделайте так, чтобы при создании новой статьи сайт валидировал данные от пользователей по следующим правилам:</p> <ul> <li data-marpit-fragment="6">Название статьи должно быть не короче 2 символов</li> <li data-marpit-fragment="7">Содержимое статьи должно быть не короче 10 символов</li> <li data-marpit-fragment="8">У статьи должно быть уникальное название</li> </ul> <p>Если данные формы валидны, сайт должен сохранять статью и выполнять редирект на страницу со списком статей <em>/articles</em>.</p> <p>Если данные не валидны, сайт должен выводить форму с заполненными полями и сообщениями об ошибках:</p> <ul> <li data-marpit-fragment="9"><em>Название не должно быть короче двух символов</em></li> <li data-marpit-fragment="10"><em>Статья должна быть не короче 10 символов</em></li> <li data-marpit-fragment="11"><em>Статья с таким названием уже существует</em></li> </ul> <h3>src/main/java/exercise/dto/articles/BuildArticlePage.java</h3> <p>Реализуйте дата-класс для передачи данных статьи в шаблон.</p> <h3>src/main/jte/articles/build.jte</h3> <p>Реализуйте шаблон для формы создания новой статьи. Поля формы должны иметь имя <em>title</em> для названия статьи и <em>content</em> для содержимого</p> <h3>Подсказки</h3> <ul> <li data-marpit-fragment="12">Для работы с данными используйте методы класса <code>ArticleRepository</code></li> <li data-marpit-fragment="13">Если хотите сделать красивый вывод в шаблонах, используйте классы Bootstrap</li> <li data-marpit-fragment="14">При ошибках валидации нужно возвращать код 422</li> <li data-marpit-fragment="15">Изучите методы контекста и найдите нужный для этого метод</li> <li data-marpit-fragment="16">Текст статьи может занимать более одной строки, поэтому мы советуем создать многострочное текстовое поле с помощью тега <code><textarea></code></li> </ul> </section> <script>!function(){"use strict";const t={h1:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"1"},style:"display: block; font-size: 2em; margin-block-start: 0.67em; margin-block-end: 0.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h2:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"2"},style:"display: block; font-size: 1.5em; margin-block-start: 0.83em; margin-block-end: 0.83em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h3:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"3"},style:"display: block; font-size: 1.17em; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h4:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"4"},style:"display: block; margin-block-start: 1.33em; margin-block-end: 1.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h5:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"5"},style:"display: block; font-size: 0.83em; margin-block-start: 1.67em; margin-block-end: 1.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h6:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"6"},style:"display: block; font-size: 0.67em; margin-block-start: 2.33em; margin-block-end: 2.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},span:{proto:()=>HTMLSpanElement},pre:{proto:()=>HTMLElement,style:"display: block; font-family: monospace; white-space: pre; margin: 1em 0; --marp-auto-scaling-white-space: pre;"}},e="data-marp-auto-scaling-wrapper",i="data-marp-auto-scaling-svg",n="data-marp-auto-scaling-container";class s extends HTMLElement{constructor(){super(),this.svgPreserveAspectRatio="xMinYMid meet";const t=t=>([e])=>{const{width:i,height:n}=e.contentRect;this[t]={width:i,height:n},this.updateSVGRect()};this.attachShadow({mode:"open"}),this.containerObserver=new ResizeObserver(t("containerSize")),this.wrapperObserver=new ResizeObserver(((...e)=>{t("wrapperSize")(...e),this.flushSvgDisplay()}))}static get observedAttributes(){return["data-downscale-only"]}connectedCallback(){var t,s,o,r,a;this.shadowRoot.innerHTML=`\n<style>\n svg[${i}] { display: block; width: 100%; height: auto; vertical-align: top; }\n span[${n}] { display: table; white-space: var(--marp-auto-scaling-white-space, nowrap); width: max-content; }\n</style>\n<div ${e}>\n <svg part="svg" ${i}>\n <foreignObject><span ${n}><slot></slot></span></foreignObject>\n </svg>\n</div>\n `.split(/\n\s*/).join(""),this.wrapper=null!==(t=this.shadowRoot.querySelector(`div[${e}]`))&&void 0!==t?t:void 0;const l=this.svg;this.svg=null!==(o=null===(s=this.wrapper)||void 0===s?void 0:s.querySelector(`svg[${i}]`))&&void 0!==o?o:void 0,this.svg!==l&&(this.svgComputedStyle=this.svg?window.getComputedStyle(this.svg):void 0),this.container=null!==(a=null===(r=this.svg)||void 0===r?void 0:r.querySelector(`span[${n}]`))&&void 0!==a?a:void 0,this.observe()}disconnectedCallback(){this.svg=void 0,this.svgComputedStyle=void 0,this.wrapper=void 0,this.container=void 0,this.observe()}attributeChangedCallback(){this.observe()}flushSvgDisplay(){const{svg:t}=this;t&&(t.style.display="inline",requestAnimationFrame((()=>{t.style.display=""})))}observe(){this.containerObserver.disconnect(),this.wrapperObserver.disconnect(),this.wrapper&&this.wrapperObserver.observe(this.wrapper),this.container&&this.containerObserver.observe(this.container),this.svgComputedStyle&&this.observeSVGStyle(this.svgComputedStyle)}observeSVGStyle(t){const e=()=>{const i=(()=>{const e=t.getPropertyValue("--preserve-aspect-ratio");if(e)return e.trim();return`x${(({textAlign:t,direction:e})=>{if(t.endsWith("left"))return"Min";if(t.endsWith("right"))return"Max";if("start"===t||"end"===t){let i="rtl"===e;return"end"===t&&(i=!i),i?"Max":"Min"}return"Mid"})(t)}YMid meet`})();i!==this.svgPreserveAspectRatio&&(this.svgPreserveAspectRatio=i,this.updateSVGRect()),t===this.svgComputedStyle&&requestAnimationFrame(e)};e()}updateSVGRect(){var t,e,i,n,s,o,r;let a=Math.ceil(null!==(e=null===(t=this.containerSize)||void 0===t?void 0:t.width)&&void 0!==e?e:0);const l=Math.ceil(null!==(n=null===(i=this.containerSize)||void 0===i?void 0:i.height)&&void 0!==n?n:0);void 0!==this.dataset.downscaleOnly&&(a=Math.max(a,null!==(o=null===(s=this.wrapperSize)||void 0===s?void 0:s.width)&&void 0!==o?o:0));const c=null===(r=this.svg)||void 0===r?void 0:r.querySelector(":scope > foreignObject");if(null==c||c.setAttribute("width",`${a}`),null==c||c.setAttribute("height",`${l}`),this.svg&&(this.svg.setAttribute("viewBox",`0 0 ${a} ${l}`),this.svg.setAttribute("preserveAspectRatio",this.svgPreserveAspectRatio),this.svg.style.height=a<=0||l<=0?"0":""),this.container){const t=this.svgPreserveAspectRatio.toLowerCase();this.container.style.marginLeft=t.startsWith("xmid")||t.startsWith("xmax")?"auto":"0",this.container.style.marginRight=t.startsWith("xmi")?"auto":"0"}}}const o=(t,{attrs:e={},style:i})=>class extends t{constructor(...t){super(...t);for(const[t,i]of Object.entries(e))this.hasAttribute(t)||this.setAttribute(t,i);this.attachShadow({mode:"open"})}static get observedAttributes(){return["data-auto-scaling"]}connectedCallback(){this._update()}attributeChangedCallback(){this._update()}_update(){const t=i?`<style>:host { ${i} }</style>`:"";let e="<slot></slot>";const{autoScaling:n}=this.dataset;if(void 0!==n){e=`<marp-auto-scaling exportparts="svg:auto-scaling" ${"downscale-only"===n?"data-downscale-only":""}>${e}</marp-auto-scaling>`}this.shadowRoot.innerHTML=t+e}};let r;const a=Symbol(),l="marpitSVGPolyfill:setZoomFactor,",c=Symbol();let d,p;function h(t){const e="object"==typeof t&&t.target||document,i="object"==typeof t?t.zoom:t;window[c]||(Object.defineProperty(window,c,{configurable:!0,value:!0}),window.addEventListener("message",(({data:t,origin:e})=>{if(e===window.origin)try{if(t&&"string"==typeof t&&t.startsWith(l)){const[,e]=t.split(","),i=Number.parseFloat(e);Number.isNaN(i)||(p=i)}}catch(t){console.error(t)}})));let n=!1;Array.from(e.querySelectorAll("svg[data-marpit-svg]"),(t=>{var e,s,o,r;t.style.transform||(t.style.transform="translateZ(0)");const a=i||p||t.currentScale||1;d!==a&&(d=a,n=a);const l=t.getBoundingClientRect(),{length:c}=t.children;for(let i=0;i<c;i+=1){const n=t.children[i];if(n.getScreenCTM){const t=n.getScreenCTM();if(t){const i=null!==(s=null===(e=n.x)||void 0===e?void 0:e.baseVal.value)&&void 0!==s?s:0,c=null!==(r=null===(o=n.y)||void 0===o?void 0:o.baseVal.value)&&void 0!==r?r:0,d=n.children.length;for(let e=0;e<d;e+=1){const s=n.children[e];if("SECTION"===s.tagName){const{style:e}=s;e.transformOrigin||(e.transformOrigin=`${-i}px ${-c}px`),e.transform=`scale(${a}) matrix(${t.a}, ${t.b}, ${t.c}, ${t.d}, ${t.e-l.left}, ${t.f-l.top}) translateZ(0.0001px)`;break}}}}}})),!1!==n&&Array.from(e.querySelectorAll("iframe"),(({contentWindow:t})=>{null==t||t.postMessage(`${l}${n}`,"null"===window.origin?"*":window.origin)}))}function g({once:t=!1,target:e=document}={}){const i="Apple Computer, Inc."===navigator.vendor?[h]:[];let n=!t;const s=()=>{for(const t of i)t({target:e});n&&window.requestAnimationFrame(s)};return s(),()=>{n=!1}}d=1,p=void 0;const m=Symbol(),v=(e=document)=>{if("undefined"==typeof window)throw new Error("Marp Core's browser script is valid only in browser context.");if(((e=document)=>{const i=window[a];i||customElements.define("marp-auto-scaling",s);for(const n of Object.keys(t)){const s=`marp-${n}`,a=t[n].proto();null!=r||(r=!!document.createElement("div",{is:"marp-auto-scaling"}).outerHTML.startsWith("<div is")),r&&a!==HTMLElement?i||customElements.define(s,o(a,{style:t[n].style}),{extends:n}):(i||customElements.define(s,o(HTMLElement,t[n])),e.querySelectorAll(`${n}[is="${s}"]`).forEach((t=>{t.outerHTML=t.outerHTML.replace(new RegExp(`^<${n}`,"i"),`<${s}`).replace(new RegExp(`</${n}>$`,"i"),`</${s}>`)})))}window[a]=!0})(e),e[m])return e[m];const i=g({target:e}),n=()=>{i(),delete e[m]},l=Object.assign(n,{cleanup:n,update:()=>v(e)});return Object.defineProperty(e,m,{configurable:!0,value:l}),l},u=document.currentScript;v(u?u.getRootNode():document)}(); </script></foreignObject></svg></div> </body> </html>