Skip to content

Commit f2362a7

Browse files
committed
Moved several projects from Aldaviva/CiscoEndpointCertificateDeployer into a new repository
0 parents  commit f2362a7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+4315
-0
lines changed

.editorconfig

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[*]
2+
3+
# Exception Analyzers: Exception adjustments syntax error
4+
# default = error
5+
; dotnet_diagnostic.Ex0001.severity = none
6+
7+
# Exception Analyzers: Exception adjustments syntax error: Symbol does not exist or identifier is invalid
8+
# default = warning
9+
; dotnet_diagnostic.Ex0002.severity = none
10+
11+
# Exception Analyzers: Member may throw undocumented exception
12+
# default = warning
13+
dotnet_diagnostic.Ex0100.severity = none
14+
15+
# Exception Analyzers: Member accessor may throw undocumented exception
16+
# default = warning
17+
dotnet_diagnostic.Ex0101.severity = none
18+
19+
# Exception Analyzers: Implicit constructor may throw undocumented exception
20+
# default = warning
21+
dotnet_diagnostic.Ex0103.severity = none
22+
23+
# Exception Analyzers: Member initializer may throw undocumented exception
24+
# default = warning
25+
dotnet_diagnostic.Ex0104.severity = none
26+
27+
# Exception Analyzers: Delegate created from member may throw undocumented exception
28+
# default = silent
29+
; dotnet_diagnostic.Ex0120.severity = none
30+
31+
# Exception Analyzers: Delegate created from anonymous function may throw undocumented exception
32+
# default = silent
33+
; dotnet_diagnostic.Ex0121.severity = none
34+
35+
# Exception Analyzers: Member is documented as throwing exception not documented on member in base or interface type
36+
# default = warning
37+
dotnet_diagnostic.Ex0200.severity = none
38+
39+
# Exception Analyzers: Member accessor is documented as throwing exception not documented on member in base or interface type
40+
# default = warning
41+
dotnet_diagnostic.Ex0201.severity = none

.github/images/readme-header.jpg

2.73 MB
Loading

.github/images/social-preview.jpg

717 KB
Loading

.gitignore

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
#Ignore thumbnails created by Windows
3+
Thumbs.db
4+
#Ignore files built by Visual Studio
5+
*.obj
6+
*.exe
7+
*.pdb
8+
*.user
9+
*.aps
10+
*.pch
11+
*.vspscc
12+
*_i.c
13+
*_p.c
14+
*.ncb
15+
*.suo
16+
*.tlb
17+
*.tlh
18+
*.bak
19+
*.cache
20+
*.ilk
21+
*.log
22+
[Bb]in
23+
[Dd]ebug*/
24+
*.lib
25+
*.sbr
26+
obj/
27+
[Rr]elease*/
28+
_ReSharper*/
29+
[Tt]est[Rr]esult*
30+
.vs/
31+
#Nuget packages folder
32+
packages/
33+
/CSxAPI/API/Generated/**/*.cs
34+
/ApiExtractor/Documentation/event*.xml

ApiExtractor/ApiExtractor.cs

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.Immutable;
4+
using System.Diagnostics;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Threading.Tasks;
8+
using ApiExtractor.Extraction;
9+
using ApiExtractor.Generation;
10+
using UglyToad.PdfPig;
11+
using UglyToad.PdfPig.Content;
12+
using UglyToad.PdfPig.Util;
13+
14+
namespace ApiExtractor;
15+
16+
internal class ApiExtractor {
17+
18+
private const string DOCUMENTATION_DIRECTORY = @"..\..\..\Documentation\";
19+
20+
public static async Task Main() {
21+
string pdfFilename = Path.Combine(DOCUMENTATION_DIRECTORY, "api-reference-guide.pdf");
22+
string eventXmlFilename = Path.Combine(DOCUMENTATION_DIRECTORY, "event.xml");
23+
24+
// dumpWordsOnPage(args); return;
25+
26+
Stopwatch stopwatch = Stopwatch.StartNew();
27+
ExtractedDocumentation docs = new();
28+
PdfReader.parsePdf(pdfFilename, docs);
29+
new EventReader(docs).parseEventXml(eventXmlFilename);
30+
new Fixes(docs).fix();
31+
await CsClientWriter.writeClient(docs);
32+
33+
stopwatch.Stop();
34+
Console.WriteLine($"Done in {stopwatch.Elapsed.TotalSeconds:N3} seconds.");
35+
}
36+
37+
private static void dumpWordsOnPage() {
38+
using PdfDocument pdf = PdfDocument.Open(Path.Combine(DOCUMENTATION_DIRECTORY, "api-reference-guide.pdf"));
39+
40+
Page page = pdf.GetPage(59);
41+
bool leftSideOfPage = false;
42+
43+
IWordExtractor wordExtractor = DefaultWordExtractor.Instance;
44+
IReadOnlyList<Letter> lettersWithUnfuckedQuotationMarks = page.Letters
45+
.Where(letter => PdfReader.isTextOnHalfOfPage(letter, page, leftSideOfPage))
46+
/*.Select(letter => letter switch {
47+
{ Value: "\"", PointSize: 9.6, FontName: var fontName } when fontName.EndsWith("CourierNewPSMT") => new Letter(
48+
letter.Value,
49+
letter.GlyphRectangle,
50+
new PdfPoint(letter.StartBaseLine.X, Math.Round(letter.StartBaseLine.Y, 4)),
51+
new PdfPoint(letter.EndBaseLine.X, Math.Round(letter.EndBaseLine.Y, 4)),
52+
letter.Width,
53+
letter.FontSize,
54+
letter.Font,
55+
letter.Color,
56+
8.8,
57+
letter.TextSequence),
58+
_ => letter
59+
})*/.ToImmutableList();
60+
IEnumerable<Word> pageText = wordExtractor.GetWords(lettersWithUnfuckedQuotationMarks);
61+
62+
// IComparer<Word> wordPositionComparer = new WordPositionComparer();
63+
foreach (Word textBlock in pageText) {
64+
Letter firstLetter = textBlock.Letters[0];
65+
// Console.WriteLine(textBlock.Text);
66+
Console.WriteLine($@"{textBlock.Text}
67+
character style = {PdfReader.getCharacterStyle(textBlock)}
68+
typeface = {firstLetter.Font.Name.Split('+', 2).Last()}
69+
point size = {firstLetter.PointSize:N3}
70+
italic = {firstLetter.Font.IsItalic}
71+
bold = {firstLetter.Font.IsBold}
72+
weight = {firstLetter.Font.Weight:N}
73+
position = ({firstLetter.Location.X:N}, {firstLetter.Location.Y:N})
74+
baseline = {firstLetter.StartBaseLine.Y:N3}
75+
bounds bottom = {textBlock.BoundingBox.Bottom:N}
76+
height (bounds) = {textBlock.BoundingBox.Height:N}
77+
height (transformed) = {firstLetter.PointSize:N}
78+
capline = {firstLetter.StartBaseLine.Y + textBlock.BoundingBox.Height:N}
79+
topline = {firstLetter.StartBaseLine.Y + firstLetter.PointSize:N}
80+
color = {firstLetter.Color}
81+
text sequence = {firstLetter.TextSequence:N0}
82+
");
83+
}
84+
}
85+
86+
}

ApiExtractor/ApiExtractor.csproj

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<LangVersion>latest</LangVersion>
7+
<Nullable>enable</Nullable>
8+
<NoWarn>CS8524, CS8846, CS8509</NoWarn>
9+
<Authors>Ben Hutchison</Authors>
10+
<Copyright>© 2023 $(Authors)</Copyright>
11+
<Company>$(Authors)</Company>
12+
<StartupObject>ApiExtractor.ApiExtractor</StartupObject>
13+
<IsPackable>false</IsPackable>
14+
</PropertyGroup>
15+
16+
<ItemGroup>
17+
<PackageReference Include="jaytwo.FluentUri" Version="0.1.4" />
18+
<PackageReference Include="morelinq" Version="3.4.2" />
19+
<PackageReference Include="PdfPig" Version="0.1.7" />
20+
</ItemGroup>
21+
22+
</Project>
852 KB
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[InternetShortcut]
2+
URL=https://www.cisco.com/c/en/us/support/collaboration-endpoints/spark-room-kit-series/products-command-reference-list.html

ApiExtractor/Extensions.cs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Collections.Generic;
2+
using System.Diagnostics.CodeAnalysis;
3+
using System.Linq;
4+
using System.Security;
5+
using System.Text.RegularExpressions;
6+
7+
namespace ApiExtractor;
8+
9+
public static class Extensions {
10+
11+
public static string? EmptyToNull(this string? original) => string.IsNullOrEmpty(original) ? null : original;
12+
13+
[return: NotNullIfNotNull(nameof(stringWithNewLines))]
14+
public static string? NewLinesToParagraphs(this string? stringWithNewLines, bool excludeOuterTags = false) =>
15+
string.IsNullOrEmpty(stringWithNewLines)
16+
? stringWithNewLines
17+
: (excludeOuterTags ? "" : "<para>") + string.Join("</para><para>", Regex.Split(stringWithNewLines, @"\r?\n").Select(SecurityElement.Escape)) + (excludeOuterTags ? "" : "</para>");
18+
19+
[return: NotNullIfNotNull(nameof(input))]
20+
public static string? ToLowerFirstLetter(this string? input) => string.IsNullOrEmpty(input) ? input : char.ToLowerInvariant(input[0]) + input[1..];
21+
22+
[return: NotNullIfNotNull(nameof(input))]
23+
public static string? ToUpperFirstLetter(this string? input) => string.IsNullOrEmpty(input) ? input : char.ToUpperInvariant(input[0]) + input[1..];
24+
25+
public static IEnumerable<T> DistinctConsecutive<T>(this IEnumerable<T> original, IEqualityComparer<T>? comparer = null) {
26+
comparer ??= EqualityComparer<T>.Default;
27+
T? previousItem = default;
28+
bool isFirstItem = true;
29+
30+
foreach (T item in original) {
31+
if (isFirstItem || !comparer.Equals(previousItem, item)) {
32+
yield return item;
33+
}
34+
35+
previousItem = item;
36+
isFirstItem = false;
37+
}
38+
}
39+
40+
}
+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Xml.Linq;
5+
6+
namespace ApiExtractor.Extraction;
7+
8+
public class EventReader {
9+
10+
private readonly ExtractedDocumentation docs;
11+
12+
public EventReader(ExtractedDocumentation docs) {
13+
this.docs = docs;
14+
}
15+
16+
public void parseEventXml(string xmlFilename) {
17+
XDocument doc = XDocument.Load(xmlFilename);
18+
19+
foreach (XElement secondLevelElements in doc.Root!.Elements()) {
20+
visit(secondLevelElements, new[] { "xEvent" });
21+
}
22+
23+
Console.WriteLine($"Parsed {docs.events.Count:N0} xEvents from XML");
24+
}
25+
26+
private void visit(XElement el, IList<string> path) {
27+
path = path.Append(el.Name.LocalName).ToList();
28+
29+
if (attributeEquals(el, "event", "True")) {
30+
DocXEvent xEvent = new() {
31+
name = path,
32+
access = EventAccessParser.parse(el.Attribute("access")!.Value),
33+
requiresUserRole = (el.Attribute("role")?.Value.Split(";").Select(rawRole => Enum.Parse<UserRole>(rawRole, true)) ?? Enumerable.Empty<UserRole>()).ToHashSet(),
34+
};
35+
36+
if (xEvent.access == EventAccess.PUBLIC_API) {
37+
docs.events.Add(xEvent);
38+
39+
foreach (XElement childEl in el.Elements()) {
40+
visit(childEl, xEvent);
41+
}
42+
}
43+
} else {
44+
foreach (XElement childEl in el.Elements()) {
45+
visit(childEl, path);
46+
}
47+
}
48+
}
49+
50+
private static void visit(XElement el, IEventParent parent) {
51+
IList<string> name = parent.name.Append(el.Attribute("className")?.Value ?? el.Name.LocalName).ToList();
52+
bool required = !attributeEquals(el, "optional", "True");
53+
54+
if (attributeEquals(el, "type", "literal") && el.HasElements) {
55+
parent.children.Add(new EnumChild {
56+
name = name,
57+
required = required,
58+
possibleValues = el.Elements("Value").Select(valueEl => new EnumValue(valueEl.Value)).ToHashSet()
59+
});
60+
} else if (attributeEquals(el, "type", "string") || (attributeEquals(el, "type", "literal") && !el.HasElements)) {
61+
parent.children.Add(new StringChild {
62+
name = name,
63+
required = required
64+
});
65+
} else if (attributeEquals(el, "type", "int")) {
66+
parent.children.Add(new IntChild {
67+
name = name,
68+
required = required,
69+
implicitAnonymousSingleton = attributeEquals(el, "onlyTextNode", "true")
70+
});
71+
} else if (attributeEquals(el, "multiple", "True")) {
72+
ListContainer listContainer = new() { name = name };
73+
parent.children.Add(listContainer);
74+
75+
foreach (XElement childEl in el.Elements()) {
76+
visit(childEl, listContainer);
77+
}
78+
} else /*if (attributeEquals(el, "basenode", "True"))*/ {
79+
ObjectContainer objectContainer = new() {
80+
name = name,
81+
required = required
82+
};
83+
parent.children.Add(objectContainer);
84+
85+
foreach (XElement childEl in el.Elements()) {
86+
visit(childEl, objectContainer);
87+
}
88+
}
89+
}
90+
91+
private static bool attributeEquals(XElement el, string attributeName, string? comparisonValue) {
92+
return string.Equals(el.Attribute(attributeName)?.Value, comparisonValue, StringComparison.InvariantCultureIgnoreCase);
93+
}
94+
95+
}

0 commit comments

Comments
 (0)