Добавьте файлы проекта.

This commit is contained in:
student 2025-04-23 15:05:44 +07:00
parent 56ed71a3f1
commit 49d479b180
13 changed files with 1235 additions and 0 deletions

152
APPdoc.csproj Normal file
View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AB18E4FD-5C49-46EF-BF2B-A8C7115EF346}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>APPdoc</RootNamespace>
<AssemblyName>APPdoc</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="AngleSharp, Version=1.2.0.0, Culture=neutral, PublicKeyToken=e83494dcdc6d31ea, processorArchitecture=MSIL">
<HintPath>packages\AngleSharp.1.2.0\lib\net472\AngleSharp.dll</HintPath>
</Reference>
<Reference Include="DocumentFormat.OpenXml, Version=3.3.0.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17, processorArchitecture=MSIL">
<HintPath>packages\DocumentFormat.OpenXml.3.3.0\lib\net46\DocumentFormat.OpenXml.dll</HintPath>
</Reference>
<Reference Include="DocumentFormat.OpenXml.Framework, Version=3.3.0.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17, processorArchitecture=MSIL">
<HintPath>packages\DocumentFormat.OpenXml.Framework.3.3.0\lib\net46\DocumentFormat.OpenXml.Framework.dll</HintPath>
</Reference>
<Reference Include="HtmlToOpenXml, Version=3.2.4.0, Culture=neutral, PublicKeyToken=6ad79d83e2b60e63, processorArchitecture=MSIL">
<HintPath>packages\HtmlToOpenXml.dll.3.2.4\lib\net462\HtmlToOpenXml.dll</HintPath>
</Reference>
<Reference Include="Markdig, Version=0.41.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Markdig.0.41.0\lib\net462\Markdig.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=9.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Bcl.AsyncInterfaces.9.0.4\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\lib\net461\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.IO.Pipelines, Version=9.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.IO.Pipelines.9.0.4\lib\net462\System.IO.Pipelines.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Memory.4.6.0\lib\net462\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encoding.CodePages, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Text.Encoding.CodePages.8.0.0\lib\net462\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encodings.Web, Version=9.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Text.Encodings.Web.9.0.4\lib\net462\System.Text.Encodings.Web.dll</HintPath>
</Reference>
<Reference Include="System.Text.Json, Version=9.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Text.Json.9.0.4\lib\net462\System.Text.Json.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\build\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\build\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>Данный проект ссылается на пакеты NuGet, отсутствующие на этом компьютере. Используйте восстановление пакетов NuGet, чтобы скачать их. Дополнительную информацию см. по адресу: http://go.microsoft.com/fwlink/?LinkID=322105. Отсутствует следующий файл: {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\build\Microsoft.Extensions.Logging.Abstractions.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\build\Microsoft.Extensions.Logging.Abstractions.targets'))" />
</Target>
</Project>

25
APPdoc.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35828.75 d17.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "APPdoc", "APPdoc.csproj", "{AB18E4FD-5C49-46EF-BF2B-A8C7115EF346}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AB18E4FD-5C49-46EF-BF2B-A8C7115EF346}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB18E4FD-5C49-46EF-BF2B-A8C7115EF346}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB18E4FD-5C49-46EF-BF2B-A8C7115EF346}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB18E4FD-5C49-46EF-BF2B-A8C7115EF346}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {45BF0B15-6273-4C05-A53E-06F937D82214}
EndGlobalSection
EndGlobal

34
App.config Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.1.0" newVersion="6.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.0" newVersion="4.0.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="DocumentFormat.OpenXml" publicKeyToken="8fb06cb64d019a17" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.3.0.0" newVersion="3.3.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="DocumentFormat.OpenXml.Framework" publicKeyToken="8fb06cb64d019a17" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.3.0.0" newVersion="3.3.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

169
Form1.Designer.cs generated Normal file
View File

@ -0,0 +1,169 @@
namespace GiteaDocGenerator
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.txtRepoUrl = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.txtSampleDocx = new System.Windows.Forms.TextBox();
this.btnSelectSample = new System.Windows.Forms.Button();
this.btnGenerate = new System.Windows.Forms.Button();
this.lblStatus = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.txtApiKey = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 15);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(143, 13);
this.label1.TabIndex = 0;
this.label1.Text = "URL репозитория Gitea:";
//
// txtRepoUrl
//
this.txtRepoUrl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtRepoUrl.Location = new System.Drawing.Point(161, 12);
this.txtRepoUrl.Name = "txtRepoUrl";
this.txtRepoUrl.Size = new System.Drawing.Size(411, 20);
this.txtRepoUrl.TabIndex = 1;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 70);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(127, 13);
this.label2.TabIndex = 5;
this.label2.Text = "Файл-пример DOCX:";
//
// txtSampleDocx
//
this.txtSampleDocx.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtSampleDocx.Location = new System.Drawing.Point(161, 67);
this.txtSampleDocx.Name = "txtSampleDocx";
this.txtSampleDocx.ReadOnly = true;
this.txtSampleDocx.Size = new System.Drawing.Size(323, 20);
this.txtSampleDocx.TabIndex = 6;
//
// btnSelectSample
//
this.btnSelectSample.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnSelectSample.Location = new System.Drawing.Point(490, 65);
this.btnSelectSample.Name = "btnSelectSample";
this.btnSelectSample.Size = new System.Drawing.Size(82, 23);
this.btnSelectSample.TabIndex = 7;
this.btnSelectSample.Text = "Выбрать...";
this.btnSelectSample.UseVisualStyleBackColor = true;
this.btnSelectSample.Click += new System.EventHandler(this.btnSelectSample_Click);
//
// btnGenerate
//
this.btnGenerate.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.btnGenerate.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.btnGenerate.Location = new System.Drawing.Point(15, 103);
this.btnGenerate.Name = "btnGenerate";
this.btnGenerate.Size = new System.Drawing.Size(557, 35);
this.btnGenerate.TabIndex = 8;
this.btnGenerate.Text = "Сгенерировать";
this.btnGenerate.UseVisualStyleBackColor = true;
this.btnGenerate.Click += new System.EventHandler(this.btnGenerate_Click);
//
// lblStatus
//
this.lblStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lblStatus.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.lblStatus.Location = new System.Drawing.Point(12, 153);
this.lblStatus.Name = "lblStatus";
this.lblStatus.Size = new System.Drawing.Size(560, 23);
this.lblStatus.TabIndex = 9;
this.lblStatus.Text = "Статус: Ожидание";
this.lblStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 43);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(107, 13);
this.label3.TabIndex = 2;
this.label3.Text = "Google AI API Key:";
//
// txtApiKey
//
this.txtApiKey.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtApiKey.Location = new System.Drawing.Point(161, 40);
this.txtApiKey.Name = "txtApiKey";
this.txtApiKey.Size = new System.Drawing.Size(411, 20);
this.txtApiKey.TabIndex = 3;
//this.txtApiKey.UseSystemPasswordChar = true; // Можно раскомментировать, чтобы скрыть ключ звездочками
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(584, 188);
this.Controls.Add(this.txtApiKey);
this.Controls.Add(this.label3);
this.Controls.Add(this.lblStatus);
this.Controls.Add(this.btnGenerate);
this.Controls.Add(this.btnSelectSample);
this.Controls.Add(this.txtSampleDocx);
this.Controls.Add(this.label2);
this.Controls.Add(this.txtRepoUrl);
this.Controls.Add(this.label1);
this.MinimumSize = new System.Drawing.Size(450, 220); // Ограничение минимального размера
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Генератор Документации Gitea + Gemini";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtRepoUrl;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtSampleDocx;
private System.Windows.Forms.Button btnSelectSample;
private System.Windows.Forms.Button btnGenerate;
private System.Windows.Forms.Label lblStatus;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox txtApiKey;
}
}

433
Form1.cs Normal file
View File

@ -0,0 +1,433 @@
using System;
using System.IO;
using System.IO.Compression; // Добавлено (или уже было) для ZipFile
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Markdig;
using HtmlToOpenXml; // Для конвертера HTML в DOCX
using System.Collections.Generic; // Для IList<>
using DocumentFormat.OpenXml; // Для OpenXmlCompositeElement
using System.Diagnostics; // <--- ДОБАВЛЕНО для Debug.WriteLine
namespace GiteaDocGenerator
{
public partial class Form1 : Form
{
private string _tempDir = string.Empty; // Для хранения скачанного кода
public Form1()
{
InitializeComponent();
}
// --- Обработчики UI ---
private void btnSelectSample_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Filter = "Word Documents (*.docx)|*.docx";
ofd.Title = "Выберите файл-пример DOCX";
if (ofd.ShowDialog() == DialogResult.OK)
{
txtSampleDocx.Text = ofd.FileName;
}
}
}
private async void btnGenerate_Click(object sender, EventArgs e)
{
string repoUrl = txtRepoUrl.Text.Trim();
string sampleDocxPath = txtSampleDocx.Text;
string apiKey = txtApiKey.Text.Trim(); // **НЕБЕЗОПАСНО!**
if (string.IsNullOrWhiteSpace(repoUrl) || !Uri.IsWellFormedUriString(repoUrl, UriKind.Absolute))
{
MessageBox.Show("Пожалуйста, введите корректный URL репозитория Gitea.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (string.IsNullOrWhiteSpace(sampleDocxPath) || !File.Exists(sampleDocxPath))
{
MessageBox.Show("Пожалуйста, выберите существующий файл-пример DOCX.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (string.IsNullOrWhiteSpace(apiKey))
{
MessageBox.Show("Пожалуйста, введите ваш Google AI API Key.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
// Блокируем UI на время работы
SetUiEnabled(false);
lblStatus.Text = "Статус: Скачивание репозитория...";
try
{
// 1. Скачивание и распаковка репозитория
_tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(_tempDir);
string zipPath = await DownloadRepoAsync(repoUrl, _tempDir);
if (string.IsNullOrEmpty(zipPath)) return; // Ошибка уже показана в DownloadRepoAsync
lblStatus.Text = "Статус: Распаковка архива...";
string extractedPath = UnzipRepo(zipPath, _tempDir);
File.Delete(zipPath); // Удаляем zip после распаковки
// Находим папку с кодом внутри (обычно имя_репо-ветка)
string repoSourcePath = Directory.GetDirectories(extractedPath).FirstOrDefault();
if (repoSourcePath == null)
{
throw new DirectoryNotFoundException("Не удалось найти папку с исходным кодом после распаковки.");
}
// 2. Подготовка данных для ИИ
lblStatus.Text = "Статус: Чтение кода и структуры примера...";
string codeContent = ReadCodeFiles(repoSourcePath); // Читаем код
string sampleStructure = ExtractStructureFromDocx(sampleDocxPath); // Читаем структуру DOCX
if (string.IsNullOrWhiteSpace(codeContent))
{
MessageBox.Show("Не удалось прочитать файлы кода из репозитория. Возможно, репозиторий пуст или содержит неподдерживаемые файлы.", "Предупреждение", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
// 3. Взаимодействие с Gemini API
lblStatus.Text = "Статус: Обращение к Google Gemini API...";
string markdownResult = await CallGeminiApiAsync(apiKey, sampleStructure, codeContent);
if (string.IsNullOrWhiteSpace(markdownResult))
{
lblStatus.Text = "Статус: Ошибка API.";
MessageBox.Show("Получен пустой ответ от Gemini API.", "Ошибка API", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 4. Создание DOCX из Markdown
lblStatus.Text = "Статус: Создание DOCX файла...";
string outputDocxPath = ShowSaveDialog();
if (!string.IsNullOrEmpty(outputDocxPath))
{
await CreateDocxFromMarkdown(markdownResult, outputDocxPath, sampleDocxPath);
lblStatus.Text = $"Статус: Готово! Файл сохранен в {outputDocxPath}";
MessageBox.Show($"Документация успешно сгенерирована и сохранена:\n{outputDocxPath}", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
lblStatus.Text = "Статус: Генерация отменена.";
}
}
catch (Exception ex)
{
lblStatus.Text = "Статус: Ошибка!";
string errorMessage = $"Произошла ошибка: {ex.Message}";
if (ex.InnerException != null)
{
errorMessage += $"\n\nВнутренняя ошибка: {ex.InnerException.Message}\n\n{ex.InnerException.StackTrace}";
}
errorMessage += $"\n\nStackTrace:\n{ex.StackTrace}";
// Если в сообщении уже есть лог Markdown/HTML (добавленный в CreateDocxFromMarkdown),
// он будет включен здесь автоматически.
MessageBox.Show(errorMessage, "Критическая ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
SetUiEnabled(true);
CleanUpTempDir();
}
}
private void SetUiEnabled(bool enabled)
{
txtRepoUrl.Enabled = enabled;
txtSampleDocx.Enabled = enabled;
btnSelectSample.Enabled = enabled;
btnGenerate.Enabled = enabled;
txtApiKey.Enabled = enabled;
}
private void CleanUpTempDir()
{
if (!string.IsNullOrEmpty(_tempDir) && Directory.Exists(_tempDir))
{
try { Directory.Delete(_tempDir, true); }
catch (Exception ex) { Console.WriteLine($"Не удалось удалить временную папку {_tempDir}: {ex.Message}"); }
_tempDir = string.Empty;
}
}
// --- Логика работы с Gitea ---
private async Task<string> DownloadRepoAsync(string repoUrl, string downloadDir)
{
Uri repoUri = new Uri(repoUrl);
string zipUrlMaster = $"{repoUri.GetLeftPart(UriPartial.Path).TrimEnd('/')}/archive/master.zip";
string zipUrlMain = $"{repoUri.GetLeftPart(UriPartial.Path).TrimEnd('/')}/archive/main.zip";
string zipPath = Path.Combine(downloadDir, "repo.zip");
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("User-Agent", "GiteaDocGeneratorApp");
HttpResponseMessage response = null;
try
{
response = await client.GetAsync(zipUrlMain);
if (!response.IsSuccessStatusCode)
{
lblStatus.Text = "Статус: Не удалось скачать main.zip, пробую master.zip...";
response.Dispose();
response = await client.GetAsync(zipUrlMaster);
}
response.EnsureSuccessStatusCode();
using (var fs = new FileStream(zipPath, FileMode.CreateNew))
{
await response.Content.CopyToAsync(fs);
}
return zipPath;
}
catch (HttpRequestException httpEx)
{
string message = $"Ошибка скачивания репозитория: {httpEx.Message}";
if (response?.StatusCode == System.Net.HttpStatusCode.NotFound)
{
message += "\nУбедитесь, что URL верный, репозиторий публичный и содержит ветку 'main' или 'master'.";
}
else if (response != null)
{
message += $"\nКод ответа: {response.StatusCode}";
}
MessageBox.Show(message, "Ошибка скачивания", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
finally
{
response?.Dispose();
}
}
}
private string UnzipRepo(string zipPath, string extractPath)
{
ZipFile.ExtractToDirectory(zipPath, extractPath);
return extractPath;
}
// --- Подготовка данных ---
private string ReadCodeFiles(string sourcePath, int maxChars = 15000)
{
StringBuilder content = new StringBuilder();
string[] extensions = { ".cs", ".md", ".txt", ".py", ".js", ".html", ".css", ".java", ".go", ".php", "Dockerfile", ".yaml", ".yml", ".json" };
string basePathWithTrailingSlash = sourcePath.EndsWith(Path.DirectorySeparatorChar.ToString()) ? sourcePath : sourcePath + Path.DirectorySeparatorChar;
Uri sourceUri = new Uri(basePathWithTrailingSlash);
var readmeFiles = Directory.GetFiles(sourcePath, "README.md", SearchOption.AllDirectories).Concat(Directory.GetFiles(sourcePath, "README.txt", SearchOption.AllDirectories));
foreach (var file in readmeFiles)
{
if (content.Length >= maxChars) break;
try
{
Uri fileUri = new Uri(file);
string relativePath = Uri.UnescapeDataString(sourceUri.MakeRelativeUri(fileUri).ToString()).Replace('/', Path.DirectorySeparatorChar);
content.AppendLine($"--- Файл: {relativePath} ---");
content.AppendLine(File.ReadAllText(file));
content.AppendLine("--- Конец файла ---");
content.AppendLine();
}
catch (Exception ex) { Console.WriteLine($"Ошибка чтения файла {file}: {ex.Message}"); }
}
var codeFiles = Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories).Where(f => extensions.Contains(Path.GetExtension(f).ToLowerInvariant()) && !Path.GetFileName(f).StartsWith("README.", StringComparison.OrdinalIgnoreCase));
foreach (var file in codeFiles)
{
if (content.Length >= maxChars) { content.AppendLine("\n[...Остальные файлы кода пропущены из-за ограничения размера...]"); break; }
try
{
string fileContent = File.ReadAllText(file);
if (!string.IsNullOrWhiteSpace(fileContent))
{
Uri fileUri = new Uri(file);
string relativePath = Uri.UnescapeDataString(sourceUri.MakeRelativeUri(fileUri).ToString()).Replace('/', Path.DirectorySeparatorChar);
content.AppendLine($"--- Файл: {relativePath} ---");
content.AppendLine(fileContent);
content.AppendLine("--- Конец файла ---");
content.AppendLine();
}
}
catch (Exception ex) { Console.WriteLine($"Ошибка чтения файла {file}: {ex.Message}"); }
}
return content.ToString();
}
private string ExtractStructureFromDocx(string docxPath)
{
StringBuilder structure = new StringBuilder();
try
{
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(docxPath, false))
{
Body body = wordDoc.MainDocumentPart.Document.Body;
foreach (var element in body.Elements<Paragraph>())
{
string styleId = element.ParagraphProperties?.ParagraphStyleId?.Val?.Value;
bool isHeading = styleId != null && styleId.StartsWith("Heading", StringComparison.OrdinalIgnoreCase) || styleId == "Заголовок";
if (isHeading) { structure.AppendLine($"{(isHeading ? "## " : "")}{element.InnerText}"); }
else if (!string.IsNullOrWhiteSpace(element.InnerText)) { if (structure.Length < 2000) { structure.AppendLine(element.InnerText); } }
}
if (structure.Length >= 2000) { structure.AppendLine("\n[...Структура примера обрезана...]"); }
}
}
catch (Exception ex)
{
MessageBox.Show($"Не удалось прочитать структуру из файла DOCX: {ex.Message}. Будет использован стандартный промпт.", "Ошибка чтения DOCX", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return "Заголовок 1\n\nВведение\n\nОсновная часть\n\nЗаключение";
}
if (string.IsNullOrWhiteSpace(structure.ToString())) { return "Заголовок 1\n\nВведение\n\nОсновная часть\n\nЗаключение"; }
return structure.ToString();
}
// --- Взаимодействие с Gemini API ---
private async Task<string> CallGeminiApiAsync(string apiKey, string sampleStructure, string codeContent)
{
string apiUrl = $"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key={apiKey}";
string prompt = $@"Сгенерируй документацию для программного продукта, исходный код которого приведен ниже.
Документация должна строго следовать структуре, представленной в следующем примере (используй заголовки и порядок разделов как в примере):
--- НАЧАЛО СТРУКТУРЫ ПРИМЕРА ---
{sampleStructure}
--- КОНЕЦ СТРУКТУРЫ ПРИМЕРА ---
Содержимое документации должно описывать код продукта. Если кода нет, напиши общую документацию по указанной структуре.
ВЕСЬ ТВОЙ ОТВЕТ ДОЛЖЕН БЫТЬ ТОЛЬКО В ФОРМАТЕ MARKDOWN. Не добавляй никаких пояснений до или после markdown.
--- НАЧАЛО КОДА ПРОДУКТА ---
{codeContent}
--- КОНЕЦ КОДА ПРОДУКТА ---
Еще раз: ВЕСЬ ТВОЙ ОТВЕТ должен быть строго в формате Markdown.";
var requestBody = new { contents = new[] { new { parts = new[] { new { text = prompt } } } }, generationConfig = new { temperature = 0.6 } };
string jsonPayload = JsonSerializer.Serialize(requestBody);
using (HttpClient client = new HttpClient())
{
try
{
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(apiUrl, content);
string responseBody = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode) { string errorDetails = TryExtractErrorFromJson(responseBody); throw new Exception($"Ошибка API Gemini: {response.StatusCode}. {errorDetails}"); }
using (JsonDocument document = JsonDocument.Parse(responseBody))
{
if (document.RootElement.TryGetProperty("candidates", out JsonElement candidates) && candidates.GetArrayLength() > 0)
{
if (candidates[0].TryGetProperty("content", out JsonElement responseContent) && responseContent.TryGetProperty("parts", out JsonElement parts) && parts.GetArrayLength() > 0)
{
if (parts[0].TryGetProperty("text", out JsonElement textElement)) { return textElement.GetString(); }
}
if (candidates[0].TryGetProperty("finishReason", out JsonElement reason))
{
string reasonStr = reason.GetString(); string safetyInfo = "";
if (reasonStr == "SAFETY" && candidates[0].TryGetProperty("safetyRatings", out JsonElement ratings)) { safetyInfo = $" Safety Ratings: {ratings.ToString()}"; }
throw new Exception($"Ответ API Gemini не содержит текст. Причина завершения: {reasonStr}.{safetyInfo}");
}
}
throw new Exception($"Не удалось извлечь текст из ответа API Gemini. Ответ:\n{responseBody}");
}
}
catch (JsonException jsonEx) { throw new Exception($"Ошибка парсинга JSON ответа от API Gemini: {jsonEx.Message}. Ответ:\n{jsonPayload}", jsonEx); }
catch (Exception ex) { throw new Exception($"Ошибка при вызове Gemini API: {ex.Message}", ex); }
}
}
private string TryExtractErrorFromJson(string jsonResponse)
{
if (string.IsNullOrWhiteSpace(jsonResponse)) return "(пустой ответ)";
try { using (JsonDocument document = JsonDocument.Parse(jsonResponse)) { if (document.RootElement.TryGetProperty("error", out JsonElement errorElement)) { if (errorElement.TryGetProperty("message", out JsonElement messageElement)) { return messageElement.GetString(); } return errorElement.ToString(); } } }
catch (JsonException) { }
return jsonResponse;
}
// --- Создание DOCX ---
private string ShowSaveDialog()
{
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Filter = "Word Document (*.docx)|*.docx"; sfd.Title = "Сохранить документацию как..."; sfd.FileName = "Generated_Documentation.docx";
if (sfd.ShowDialog() == DialogResult.OK) { return sfd.FileName; }
return null;
}
}
// Метод остается асинхронным (async Task)
// Метод остается асинхронным (async Task)
private async Task CreateDocxFromMarkdown(string markdown, string outputPath, string sampleDocxPath)
{
// --- Логирование Markdown ---
Debug.WriteLine("--- ИСХОДНЫЙ MARKDOWN ---");
Debug.WriteLine(markdown ?? "[NULL]");
Debug.WriteLine("--- КОНЕЦ MARKDOWN ---");
// ---------------------------
var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
string html = "[NULL]";
if (markdown != null)
{
html = Markdown.ToHtml(markdown, pipeline);
}
// --- Логирование HTML ---
Debug.WriteLine("--- ПОЛУЧЕННЫЙ HTML ---");
Debug.WriteLine(html);
Debug.WriteLine("--- КОНЕЦ HTML ---");
// ------------------------
try
{
// Шаг 1: Клонирование шаблона. Шаблон будет закрыт сразу после клонирования.
using (WordprocessingDocument templateDoc = WordprocessingDocument.Open(sampleDocxPath, false))
{
// Клонируем шаблон в ВЫХОДНОЙ файл и открываем для редактирования
using (WordprocessingDocument wordDoc = (WordprocessingDocument)templateDoc.Clone(outputPath, true))
{
// Шаг 2: Работа с клонированным документом (wordDoc)
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
Body body = mainPart.Document.Body;
// !!! ОЧИЩАЕМ ТЕЛО ДОКУМЕНТА !!!
body.RemoveAllChildren<Paragraph>();
body.RemoveAllChildren<Table>();
// Шаг 3: Используем HtmlConverter для преобразования HTML и добавления в пустое тело
HtmlConverter converter = new HtmlConverter(mainPart);
await converter.ParseHtml(html); // ParseHtml добавляет элементы в mainPart.Document.Body
// Шаг 4: Плейсхолдер НЕ НУЖЕН и его поиск/удаление НЕ НУЖНЫ
// Сохранение происходит автоматически при выходе из using (wordDoc)
} // wordDoc закрывается и сохраняется здесь
} // templateDoc закрывается здесь
}
catch (IOException ioEx)
{
string logInfo = $"\n\n--- Markdown Log ---\n{markdown ?? "[NULL]"}\n--- HTML Log ---\n{html}";
throw new IOException($"Ошибка доступа к файлу при клонировании/создании DOCX '{outputPath}': {ioEx.Message}. Убедитесь, что файл не открыт в другой программе.{logInfo}", ioEx);
}
catch (Exception ex)
{
// Убираем проверку на InvalidOperationException, так как плейсхолдера нет
string logInfo = $"\n\n--- Markdown Log ---\n{markdown ?? "[NULL]"}\n--- HTML Log ---\n{html}";
throw new Exception($"Ошибка при создании DOCX файла из Markdown/HTML:\n{ex.Message}{logInfo}", ex);
}
}
}
}

120
Form1.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

23
Program.cs Normal file
View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using GiteaDocGenerator; // <--- ДОБАВЛЕННАЯ СТРОКА
namespace APPdoc // Или другое имя корневого пространства имен вашего проекта
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1()); // Теперь компилятор знает, где искать Form1
}
}
}

View File

@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Общие сведения об этой сборке предоставляются следующим набором
// набора атрибутов. Измените значения этих атрибутов для изменения сведений,
// связанных со сборкой.
[assembly: AssemblyTitle("APPdoc")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("APPdoc")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми
// для компонентов COM. Если необходимо обратиться к типу в этой сборке через
// COM, следует установить атрибут ComVisible в TRUE для этого типа.
[assembly: ComVisible(false)]
// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
[assembly: Guid("ab18e4fd-5c49-46ef-bf2b-a8c7115ef346")]
// Сведения о версии сборки состоят из указанных ниже четырех значений:
//
// Основной номер версии
// Дополнительный номер версии
// Номер сборки
// Редакция
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

71
Properties/Resources.Designer.cs generated Normal file
View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Этот код создан программным средством.
// Версия среды выполнения: 4.0.30319.42000
//
// Изменения в этом файле могут привести к неправильному поведению и будут утрачены, если
// код создан повторно.
// </auto-generated>
//------------------------------------------------------------------------------
namespace APPdoc.Properties
{
/// <summary>
/// Класс ресурсов со строгим типом для поиска локализованных строк и пр.
/// </summary>
// Этот класс был автоматически создан при помощи StronglyTypedResourceBuilder
// класс с помощью таких средств, как ResGen или Visual Studio.
// Для добавления или удаления члена измените файл .ResX, а затем перезапустите ResGen
// с параметром /str или заново постройте свой VS-проект.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Возврат кэшированного экземпляра ResourceManager, используемого этим классом.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("APPdoc.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Переопределяет свойство CurrentUICulture текущего потока для всех
/// подстановки ресурсов с помощью этого класса ресурсов со строгим типом.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

117
Properties/Resources.resx Normal file
View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

30
Properties/Settings.Designer.cs generated Normal file
View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace APPdoc.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

21
packages.config Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AngleSharp" version="1.2.0" targetFramework="net472" />
<package id="DocumentFormat.OpenXml" version="3.3.0" targetFramework="net472" />
<package id="DocumentFormat.OpenXml.Framework" version="3.3.0" targetFramework="net472" />
<package id="HtmlToOpenXml.dll" version="3.2.4" targetFramework="net472" />
<package id="Markdig" version="0.41.0" targetFramework="net472" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="9.0.4" targetFramework="net472" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="6.0.0" targetFramework="net472" />
<package id="System.Buffers" version="4.6.0" targetFramework="net472" />
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net472" />
<package id="System.IO.Pipelines" version="9.0.4" targetFramework="net472" />
<package id="System.Memory" version="4.6.0" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.6.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.0" targetFramework="net472" />
<package id="System.Text.Encoding.CodePages" version="8.0.0" targetFramework="net472" />
<package id="System.Text.Encodings.Web" version="9.0.4" targetFramework="net472" />
<package id="System.Text.Json" version="9.0.4" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
</packages>