React 16x - قسمت 1 - معرفی و شروع به کار
npx create-react-app my-app cd my-app npm start
<Style TargetType="Label"> <Setter Property="FontFamily" Value="Some font..." /> </Style>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True" > <Setter Property="BackgroundColor" Value="Blue" /> </Style>
<Style x:Key="DangerButton" TargetType="Button"> <Setter Property="BackgroundColor" Value="Red" /> <Setter Property="FontAttributes" Value="Bold" /> </Style>
<Button Style="{StaticResource DangerButton}" />
<Style TargetType="Entry"> <Style.Triggers> <Trigger TargetType="Entry" Property="IsFocused" Value="True"> <Setter Property="FontAttributes" Value="Bold" /> </Trigger> </Style.Triggers> </Style>
<StyleSheet> <![CDATA[ button { font-style: bold; } ]]> </StyleSheet>
<key>UIAppFonts</key> <array> <string>Fonts/OpenSansItalic.ttf</string> <string>Fonts/OpenSansRegular.ttf</string> <string>Fonts/OpenSansBold.ttf</string> </array>
سپس کدهای زیر را استفاده کنید:
<bitView:OnPlatform x:Key="OpenSansRegular" x:TypeArguments="x:String" Value="{OnPlatform Android='Fonts/OpenSansRegular.ttf#Open Sans', iOS='OpenSans-Regular', UWP='Assets/Fonts/OpenSansRegular.ttf#Open Sans'}" /> <!-- Italic مشابه کد بالا برای --> <!-- Bold مشابه کد بالا برای -->
چون آدرس و نحوه نام دهی FontFamily در سه پلتفرم متفاوت است، با استفاده از OnPlatform، یک String میسازیم با x:Key برابر با OpenSansRegular که در هر پلتفرم مقدار خود را دارد. سپس از این نام برای مقدار دهی FontFamily در کنترلهای Label/Entry/Button و ... در حالتهای None/Italic/Bold استفاده میکنیم. برای مثال:
<Style TargetType="Label"> <Style.Triggers> <Trigger TargetType="Label" Property="FontAttributes" Value="Bold"> <Setter Property="FontFamily" Value="{StaticResource OpenSansBold}" /> </Trigger> <Trigger TargetType="Label" Property="FontAttributes" Value="Italic"> <Setter Property="FontFamily" Value="{StaticResource OpenSansItalic}" /> </Trigger> <Trigger TargetType="Label" Property="FontAttributes" Value="None"> <Setter Property="FontFamily" Value="{StaticResource OpenSansRegular}" /> </Trigger> </Style.Triggers> </Style>
این کد میگوید زمانیکه FontAttributes یک Label برابر با Bold است، از OpenSansBold برای FontFamily اش استفاده شود و همینطور برای Italic و None (یا همان Regular)
در قسمتیکه داشتیم برای اندروید و ویندوز، مسیر فایل فونت را مشخص میکردیم، از مقدار OpenSansRegular.ttf#Open Sans استفاده کردیم که OpenSansRegular.ttf نام فیزیکی فایل و Open Sans نام خود فایل است که با دو بار کلیک کردن روی فایل آن در ویندوز از طریق برنامه Font ویندوز قابل مشاهده است:
همچنین برای اینکه این سه فایل، سه بار برای سه پلتفرم در سورس کنترلر کپی نشوند، از روش Add as link در Visual Studio بهره گرفتهایم و فایل فیزیکی فونتها فقط در پروژه UWP وجود دارند. البته این به معنای این نیست که در Apk نهایی Android و ipa نهایی iOS این فایلها وجود نخواهند داشت؛ بلکه به خاطر ماهیت Add as link، انگار که این فایلها در هر سه پروژه هستند و پشت صحنه کپی میشوند.
بهبود ظاهر کامنتها با بکارگیری Markdown
Markdown زبان سبکی است برای تعیین شیوهنامهی نمایش متون ساده. اگر پیشتر با سیستم ارسال نظرات Github و یا Stackoverflow کار کرده باشید، قطعا با آن آشنایی دارید. توضیحات کامل و جزئیات آنرا میتوانید در آدرس markdownguide.org مطالعه کنید. خوشبختانه امکان استفادهی از Markdown در OpenAPI spec نیز وجود دارد که سبب بهبود ظاهر مستندات نهایی حاصل از آن خواهد شد.
در قسمت سوم، سعی کردیم مثالی را توسط remarks، به قسمت Patch اضافه کنیم که ظاهر آن، آنچنان مطلوب به نظر نمیرسد و بهتر است آنرا به صورت یک قطعه کد نمایش داد:
برای بهبود این ظاهر میتوان از Markdown استفاده کرد. بنابراین ابتدا تمام backslashهای اضافه شده را که جهت نمایش خطوط جدید اضافه شده بودند، حذف میکنیم. در Markdown خطوط جدید با درج حداقل 2 فاصله (space) و یک سطر جدید مشخص میشوند. همچنین استفادهی از ** سبب ضخیم شدن نمایش عبارتها میشود. برای اینکه قطعه کد نوشته شده را در Markdown به صورت کدی با پس زمینهای مشخص نمایش دهیم، پیش از شروع هر سطر آن نیاز است یک tab و یا 4 فاصله (space) درج شوند:
/// <remarks> /// Sample request (this request updates the author's **first name**) /// /// PATCH /authors/id /// [ /// { /// "op": "replace", /// "path": "/firstname", /// "value": "new first name" /// } /// ] /// </remarks>
که نسبت به حالت قبلی بسیار بهتر به نظر میرسد.
در نگارش فعلی، استفادهی از Markdown برای توضیحات remarks، پارامترها و response codes پشتیبانی میشود؛ اما نه برای قسمت summary که برای نگارش بعدی درنظر گرفته شدهاست. همچنین از قابلیتهای پیشترفتهی Markdown هم استفاده نکنید (در کل نیاز به مقداری سعی و خطا دارد تا مشخص شود چه قابلیتهایی را پشتیبانی میکند).
سفارشی سازی مقدماتی UI به کمک تنظیمات API آن
جائیکه تنظیمات میانافزار Swashbuckle.AspNetCore در کلاس Starup تعریف میشوند، میتوان تغییراتی را نیز در UI آن اعمال کرد:
namespace OpenAPISwaggerDoc.Web { public class Startup { public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // ... app.UseSwaggerUI(setupAction => { setupAction.SwaggerEndpoint( url: "/swagger/LibraryOpenAPISpecification/swagger.json", name: "Library API"); setupAction.RoutePrefix = ""; setupAction.DefaultModelExpandDepth(2); setupAction.DefaultModelRendering(Swashbuckle.AspNetCore.SwaggerUI.ModelRendering.Model); setupAction.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None); setupAction.EnableDeepLinking(); setupAction.DisplayOperationId(); }); // ... } } }
همچنین چون DefaultModelRendering به Model تنظیم شدهاست، اینبار بجای مثال، مشخصات مدل را به صورت پیشفرض نمایش میدهد:
کار DisplayOperationId نمایش Id هر Operation است؛ مانند get_api_authors. در اینجا Operation همان مداخل API ما هستند و به عنوان هر قسمت، Tag گفته میشود؛ مانند Authors و یا Books:
با فعالسازی EnableDeepLinking، آدرسهایی مانند tagName/# و یا tagName/OperationId/# قابلیت مرور و بازشدن خودکار را پیدا میکنند (tagName همان نام کنترلر است و OperationId همان اکشن متدی که عمومی شدهاست). برای مثال اگر آدرس https://localhost:5001/index.html#/Books/get_api_authors__authorId__books را در یک برگهی جدید مرورگر باز کنیم، بلافاصله گروه Books، باز شده و سپس به اکشن متد یا مدخلی که Id آن ذکر شدهاست، هدایت میشویم:
اعمال تغییرات پیشرفته در UI
Swagger-UI در اصل از یک سری فایل html، css، js و فونت تشکیل شدهاست که آنها را میتوانید در آدرس src/Swashbuckle.AspNetCore.SwaggerUI مشاهده کنید. برای مثال فایل index.html آنرا در اینجا میتوانید مشاهده کنید. اصل آن در div ای با id مساوی swagger-ui رخ میدهد و در این قسمت است که رابط کاربری آن به صورت پویا تولید شده و رندر خواهد شد. بررسی فایلهای js و css آن در این مخزن کد مشکل است؛ چون نگارش فشرده شدهی آن هستند. به همین جهت میتوان به مخزن کد اصلی Swagger-UI که نگارش جایگذاری شدهی آن (embedded) توسط Swashbuckle.AspNetCore ارائه میشود، رجوع کرد. برای مثال در پوشهی src/styles آن، اصل فایلهای css آن برای سفارشی سازی وجود دارند.
پس از اعمال تغییرات خود، میتوانید css و یا js سفارشی خود را به نحو زیر به تنظیمات app.UseSwaggerUI سیستم معرفی کنید:
setupAction.InjectStylesheet("/Assets/custom-ui.css"); setupAction.InjectJavaScript("/Assets/custom-js.js");
برای اعمال تغییرات اساسی و تزریق صفحهی index.html جدیدی، میتوان به صورت زیر عمل کرد:
setupAction.IndexStream = () => GetType().Assembly.GetManifestResourceStream( "OpenAPISwaggerDoc.Web.EmbeddedAssets.index.html");
<Project Sdk="Microsoft.NET.Sdk.Web"> <ItemGroup> <None Remove="EmbeddedAssets\index.html" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="EmbeddedAssets\index.html" /> </ItemGroup> </Project>
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: OpenAPISwaggerDoc-07.zip
معرفی Blazor Hybrid
- در Blazor Web Assembly که UI با HTML / CSS زده میشود، کدهای C# .NET ای با کمک Web Assembly و داخل خود مرورگر اجرا میشوند. با کمک Blazor Web Assembly میتوان محصولات PWA و SPA ایجاد نمود.
- در Blazor Server که UI با HTML / CSS زده میشود، کدها در سرور اجرا و به وسیلهی Web Sockets، تعاملات UI ای از Browser به سرور ارسال و تغییرات UI ای از سرور به Browser ارسال میشوند. با کمک Blazor Server میتوان محصولات SPA ایجاد نمود.
- Blazor Native Mobile Apps که در این روش از کامپوننتهای Native موبایل استفاده میشود؛ نه عناصر HTML مانند h1 و div. با کمک Blazor Native Mobile Apps میتوان برنامههای Native موبایل برای Android / iOS و برنامههای Desktop برای Windows ایجاد نمود.
- Blazor Hybrid که در این روش UI با HTML / CSS بوده، ولی اجرای کدهای C# .NET داخل خود سیستم عامل و به صورت Native است. با کمک Blazor Hybrid میتوان برنامههای موبایل برای Android / iOS و برنامههای Desktop برای Windows ایجاد نمود.