Skip to content

Commit a3f4175

Browse files
authored
added generation of DeviceDescriptors.cs (#591)
added generation of DeviceDescriptors.cs
1 parent f2e27c7 commit a3f4175

File tree

9 files changed

+643
-97
lines changed

9 files changed

+643
-97
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Collections.Generic;
2+
3+
namespace PuppeteerSharp.DevicesFetcher
4+
{
5+
public class DevicePayload
6+
{
7+
public string Type { get; set; }
8+
9+
public string UserAgent { get; set; }
10+
11+
public ViewportPayload Vertical { get; set; }
12+
13+
public ViewportPayload Horizontal { get; set; }
14+
15+
public double DeviceScaleFactor { get; set; }
16+
17+
public HashSet<string> Capabilities { get; set; }
18+
}
19+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using Newtonsoft.Json;
2+
3+
namespace PuppeteerSharp.DevicesFetcher
4+
{
5+
public class RootObject
6+
{
7+
[JsonProperty("extensions")]
8+
public Extension[] Extensions { get; set; }
9+
10+
public class Extension
11+
{
12+
[JsonProperty("type")]
13+
public string Type { get; set; }
14+
[JsonProperty("device")]
15+
public Device Device { get; set; }
16+
}
17+
18+
public class Device
19+
{
20+
[JsonProperty("show-by-default")]
21+
public bool ShowByDefault { get; set; }
22+
[JsonProperty("title")]
23+
public string Title { get; set; }
24+
[JsonProperty("screen")]
25+
public Screen Screen { get; set; }
26+
[JsonProperty("capabilities")]
27+
public string[] Capabilities { get; set; }
28+
[JsonProperty("user-agent")]
29+
public string UserAgent { get; set; }
30+
[JsonProperty("type")]
31+
public string Type { get; set; }
32+
}
33+
34+
public class Screen
35+
{
36+
[JsonProperty("horizontal")]
37+
public ViewportPayload Horizontal { get; set; }
38+
[JsonProperty("device-pixel-ratio")]
39+
public double DevicePixelRatio { get; set; }
40+
[JsonProperty("vertical")]
41+
public ViewportPayload Vertical { get; set; }
42+
}
43+
}
44+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace PuppeteerSharp.DevicesFetcher
2+
{
3+
public class OutputDevice
4+
{
5+
public string Name { get; set; }
6+
public string UserAgent { get; set; }
7+
public OutputDeviceViewport Viewport { get; set; }
8+
9+
public class OutputDeviceViewport
10+
{
11+
public double Width { get; set; }
12+
13+
public double Height { get; set; }
14+
15+
public double DeviceScaleFactor { get; set; }
16+
17+
public bool IsMobile { get; set; }
18+
19+
public bool HasTouch { get; set; }
20+
21+
public bool IsLandscape { get; set; }
22+
}
23+
}
24+
}
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Net.Http;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Newtonsoft.Json;
9+
using Newtonsoft.Json.Linq;
10+
11+
namespace PuppeteerSharp.DevicesFetcher
12+
{
13+
class Program
14+
{
15+
const string DEVICES_URL = "https://raw.githubusercontent.com/ChromeDevTools/devtools-frontend/master/front_end/emulated_devices/module.json";
16+
17+
static string deviceDescriptorsOutput = "../../../../PuppeteerSharp/Mobile/DeviceDescriptors.cs";
18+
static string deviceDescriptorNameOutput = "../../../../PuppeteerSharp/Mobile/DeviceDescriptorName.cs";
19+
20+
static async Task Main(string[] args)
21+
{
22+
var url = DEVICES_URL;
23+
if (args.Length > 0)
24+
{
25+
url = args[0];
26+
}
27+
28+
string chromeVersion = null;
29+
var fetcher = new BrowserFetcher();
30+
await fetcher.DownloadAsync(BrowserFetcher.DefaultRevision);
31+
using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions()))
32+
{
33+
chromeVersion = (await browser.GetVersionAsync()).Split('/').Last();
34+
}
35+
36+
Console.WriteLine($"GET {url}");
37+
var text = await HttpGET(url);
38+
RootObject json = null;
39+
try
40+
{
41+
json = JsonConvert.DeserializeObject<RootObject>(text);
42+
}
43+
catch (Exception ex)
44+
{
45+
Console.WriteLine($"FAILED: error parsing response - {ex.Message}");
46+
}
47+
var devicePayloads = json.Extensions
48+
.Where(extension => extension.Type == "emulated-device")
49+
.Select(extension => extension.Device)
50+
.ToArray();
51+
var devices = new List<OutputDevice>();
52+
foreach (var payload in devicePayloads)
53+
{
54+
string[] names;
55+
if (payload.Title == "iPhone 6/7/8")
56+
{
57+
names = new[] { "iPhone 6", "iPhone 7", "iPhone 8" };
58+
}
59+
else if (payload.Title == "iPhone 6/7/8 Plus")
60+
{
61+
names = new[] { "iPhone 6 Plus", "iPhone 7 Plus", "iPhone 8 Plus" };
62+
}
63+
else if (payload.Title == "iPhone 5/SE")
64+
{
65+
names = new[] { "iPhone 5", "iPhone SE" };
66+
}
67+
else
68+
{
69+
names = new[] { payload.Title };
70+
}
71+
foreach (var name in names)
72+
{
73+
var device = CreateDevice(chromeVersion, name, payload, false);
74+
var landscape = CreateDevice(chromeVersion, name, payload, true);
75+
devices.Add(device);
76+
if (landscape.Viewport.Width != device.Viewport.Width || landscape.Viewport.Height != device.Viewport.Height)
77+
{
78+
devices.Add(landscape);
79+
}
80+
}
81+
}
82+
devices.RemoveAll(device => !device.Viewport.IsMobile);
83+
devices.Sort((a, b) => a.Name.CompareTo(b.Name));
84+
85+
WriteDeviceDescriptors(devices);
86+
WriteDeviceDescriptorName(devices);
87+
}
88+
89+
static void WriteDeviceDescriptors(IEnumerable<OutputDevice> devices)
90+
{
91+
var builder = new StringBuilder();
92+
var begin = @"using System.Collections.Generic;
93+
94+
namespace PuppeteerSharp.Mobile
95+
{
96+
/// <summary>
97+
/// Device descriptors.
98+
/// </summary>
99+
public class DeviceDescriptors
100+
{
101+
private static readonly Dictionary<DeviceDescriptorName, DeviceDescriptor> Devices = new Dictionary<DeviceDescriptorName, DeviceDescriptor>
102+
{
103+
";
104+
var end = @"
105+
};
106+
107+
/// <summary>
108+
/// Get the specified device description.
109+
/// </summary>
110+
/// <returns>The device descriptor.</returns>
111+
/// <param name=""name"">Device Name.</param>
112+
public static DeviceDescriptor Get(DeviceDescriptorName name) => Devices[name];
113+
}
114+
}";
115+
116+
builder.Append(begin);
117+
builder.AppendJoin(",\n", devices.Select(GenerateCsharpFromDevice));
118+
builder.Append(end);
119+
120+
File.WriteAllText(deviceDescriptorsOutput, builder.ToString());
121+
}
122+
123+
static void WriteDeviceDescriptorName(IEnumerable<OutputDevice> devices)
124+
{
125+
var builder = new StringBuilder();
126+
var begin = @"namespace PuppeteerSharp.Mobile
127+
{
128+
/// <summary>
129+
/// Device descriptor name.
130+
/// </summary>
131+
public enum DeviceDescriptorName
132+
{";
133+
var end = @"
134+
}
135+
}";
136+
137+
builder.Append(begin);
138+
builder.AppendJoin(",", devices.Select(device =>
139+
{
140+
return $@"
141+
/// <summary>
142+
/// {device.Name}
143+
/// </summary>
144+
{DeviceNameToEnumValue(device)}";
145+
}));
146+
builder.Append(end);
147+
148+
File.WriteAllText(deviceDescriptorNameOutput, builder.ToString());
149+
}
150+
151+
static string GenerateCsharpFromDevice(OutputDevice device)
152+
{
153+
var w = string.Empty;
154+
return $@" [DeviceDescriptorName.{DeviceNameToEnumValue(device)}] = new DeviceDescriptor
155+
{{
156+
Name = ""{device.Name}"",
157+
UserAgent = ""{device.UserAgent}"",
158+
ViewPort = new ViewPortOptions
159+
{{
160+
Width = {device.Viewport.Width},
161+
Height = {device.Viewport.Height},
162+
DeviceScaleFactor = {device.Viewport.DeviceScaleFactor},
163+
IsMobile = {device.Viewport.IsMobile.ToString().ToLower()},
164+
HasTouch = {device.Viewport.HasTouch.ToString().ToLower()},
165+
IsLandscape = {device.Viewport.IsLandscape.ToString().ToLower()}
166+
}}
167+
}}";
168+
}
169+
static string DeviceNameToEnumValue(OutputDevice device)
170+
{
171+
var output = new StringBuilder();
172+
output.Append(char.ToUpper(device.Name[0]));
173+
for (var i = 1; i < device.Name.Length; i++)
174+
{
175+
if (char.IsWhiteSpace(device.Name[i]))
176+
{
177+
output.Append(char.ToUpper(device.Name[i + 1]));
178+
i++;
179+
}
180+
else
181+
{
182+
output.Append(device.Name[i]);
183+
}
184+
}
185+
186+
return output.ToString();
187+
}
188+
189+
static OutputDevice CreateDevice(string chromeVersion, string deviceName, RootObject.Device descriptor, bool landscape)
190+
{
191+
var devicePayload = LoadFromJSONV1(descriptor);
192+
var viewportPayload = landscape ? devicePayload.Horizontal : devicePayload.Vertical;
193+
return new OutputDevice
194+
{
195+
Name = deviceName + (landscape ? " landscape" : string.Empty),
196+
UserAgent = devicePayload.UserAgent.Replace("%s", chromeVersion),
197+
Viewport = new OutputDevice.OutputDeviceViewport
198+
{
199+
Width = viewportPayload.Width,
200+
Height = viewportPayload.Height,
201+
DeviceScaleFactor = devicePayload.DeviceScaleFactor,
202+
IsMobile = devicePayload.Capabilities.Contains("mobile"),
203+
HasTouch = devicePayload.Capabilities.Contains("touch"),
204+
IsLandscape = landscape
205+
}
206+
};
207+
}
208+
209+
static DevicePayload LoadFromJSONV1(RootObject.Device json) => new DevicePayload
210+
{
211+
Type = json.Type,
212+
UserAgent = json.UserAgent,
213+
Capabilities = json.Capabilities.ToHashSet(),
214+
DeviceScaleFactor = json.Screen.DevicePixelRatio,
215+
Horizontal = new ViewportPayload
216+
{
217+
Height = json.Screen.Horizontal.Height,
218+
Width = json.Screen.Horizontal.Width
219+
},
220+
Vertical = new ViewportPayload
221+
{
222+
Height = json.Screen.Vertical.Height,
223+
Width = json.Screen.Vertical.Width
224+
}
225+
};
226+
227+
static Task<string> HttpGET(string url) => new HttpClient().GetStringAsync(url);
228+
}
229+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp2.0</TargetFramework>
6+
<LangVersion>7.2</LangVersion>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<ProjectReference Include="..\PuppeteerSharp\PuppeteerSharp.csproj" />
15+
</ItemGroup>
16+
17+
</Project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Newtonsoft.Json;
2+
3+
namespace PuppeteerSharp.DevicesFetcher
4+
{
5+
public class ViewportPayload
6+
{
7+
[JsonProperty("width")]
8+
public double Width { get; set; }
9+
10+
[JsonProperty("height")]
11+
public double Height { get; set; }
12+
}
13+
}

lib/PuppeteerSharp.sln

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio 15
33
VisualStudioVersion = 15.0.27703.2035
44
MinimumVisualStudioVersion = 10.0.40219.1
@@ -12,6 +12,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PuppeteerSharp.Tests.DumpIO
1212
EndProject
1313
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PuppeteerSharp.Tests.CloseMe", "PuppeteerSharp.Tests.CloseMe\PuppeteerSharp.Tests.CloseMe.csproj", "{B1B0358F-88A2-4038-9974-7850D906C76B}"
1414
EndProject
15+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PuppeteerSharp.DevicesFetcher", "PuppeteerSharp.DevicesFetcher\PuppeteerSharp.DevicesFetcher.csproj", "{A500694A-3649-4474-BC71-C835FA19B865}"
16+
EndProject
1517
Global
1618
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1719
Debug|Any CPU = Debug|Any CPU
@@ -38,6 +40,10 @@ Global
3840
{B1B0358F-88A2-4038-9974-7850D906C76B}.Debug|Any CPU.Build.0 = Debug|Any CPU
3941
{B1B0358F-88A2-4038-9974-7850D906C76B}.Release|Any CPU.ActiveCfg = Release|Any CPU
4042
{B1B0358F-88A2-4038-9974-7850D906C76B}.Release|Any CPU.Build.0 = Release|Any CPU
43+
{A500694A-3649-4474-BC71-C835FA19B865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44+
{A500694A-3649-4474-BC71-C835FA19B865}.Debug|Any CPU.Build.0 = Debug|Any CPU
45+
{A500694A-3649-4474-BC71-C835FA19B865}.Release|Any CPU.ActiveCfg = Release|Any CPU
46+
{A500694A-3649-4474-BC71-C835FA19B865}.Release|Any CPU.Build.0 = Release|Any CPU
4147
EndGlobalSection
4248
GlobalSection(SolutionProperties) = preSolution
4349
HideSolutionNode = FALSE

0 commit comments

Comments
 (0)