Skip to content

Commit 38c3415

Browse files
committed
feat(developer): add relatedPackages metadata
Adds relatedPackages support to: * .kps schema * .kps file format for Typescript * kmp.json file format for Typescript * kmc-package compiler * Package Editor
1 parent d838df1 commit 38c3415

File tree

15 files changed

+592
-28
lines changed

15 files changed

+592
-28
lines changed

common/schemas/kps/kps.xsd

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@
9797
</xs:complexType>
9898
</xs:element>
9999

100+
<xs:element minOccurs="0" maxOccurs="1" name="RelatedPackages">
101+
<xs:complexType>
102+
<xs:sequence>
103+
<xs:element minOccurs="0" maxOccurs="unbounded" name="RelatedPackage">
104+
<xs:complexType>
105+
<xs:attribute name="ID" type="xs:string" />
106+
<!-- "deprecates" is only valid value, if not present then means "related" -->
107+
<xs:attribute name="Relationship" type="km-package-relationship" />
108+
</xs:complexType>
109+
</xs:element>
110+
</xs:sequence>
111+
</xs:complexType>
112+
</xs:element>
100113

101114
<xs:element minOccurs="0" maxOccurs="1" name="Keyboards">
102115
<xs:complexType>
@@ -137,6 +150,7 @@
137150
</xs:complexType>
138151
</xs:element>
139152

153+
<!-- Deprecated elements: we won't validate as processors ignore them -->
140154

141155
<xs:element minOccurs="0" maxOccurs="1" name="Strings">
142156
<xs:complexType>
@@ -151,8 +165,6 @@
151165
</xs:complexType>
152166
</xs:element>
153167

154-
<!-- Deprecated elements: we won't validate as processors ignore them -->
155-
156168
<xs:element minOccurs="0" maxOccurs="1" name="Buttons" type="km-any" />
157169
<xs:element minOccurs="0" maxOccurs="1" name="Registry" type="km-any" />
158170

@@ -191,6 +203,12 @@
191203
</xs:restriction>
192204
</xs:simpleType>
193205

206+
<xs:simpleType name="km-package-relationship">
207+
<xs:restriction base="xs:string">
208+
<xs:pattern value="deprecates" />
209+
</xs:restriction>
210+
</xs:simpleType>
211+
194212
<xs:simpleType name="km-start-menu-location">
195213
<xs:restriction base="xs:string">
196214
<xs:pattern value="psmelStartMenu|psmelDesktop"></xs:pattern>

common/web/types/src/package/kmp-json-file.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export interface KmpJsonFile {
66
lexicalModels?: KmpJsonFileLexicalModel[];
77
startMenu?: KmpJsonFileStartMenu;
88
keyboards?: KmpJsonFileKeyboard[];
9+
relatedPackages?: KmpJsonRelatedPackage[];
910
}
1011

1112
export interface KmpJsonFileSystem {
@@ -103,4 +104,9 @@ export interface KmpJsonFileExample {
103104
* A short description of what the text means or represents
104105
*/
105106
note?: string;
106-
}
107+
}
108+
109+
export interface KmpJsonRelatedPackage {
110+
id: string;
111+
relationship: "deprecates" | "related";
112+
}

common/web/types/src/package/kps-file.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export interface KpsFile {
2929
lexicalModels?: KpsFileLexicalModels;
3030
startMenu?: KpsFileStartMenu;
3131
strings?: KpsFileStrings;
32+
relatedPackages?: KpsFileRelatedPackages;
3233
}
3334

3435
export interface KpsFileSystem {
@@ -92,6 +93,20 @@ export interface KpsFileLanguage {
9293
$: { ID: string }
9394
}
9495

96+
export interface KpsFileRelatedPackages {
97+
relatedPackage: KpsFileRelatedPackage | KpsFileRelatedPackage[];
98+
}
99+
100+
export interface KpsFileRelatedPackage {
101+
$: {
102+
ID: string;
103+
/**
104+
* relationship between this package and the related package, "related" is default if not specified
105+
*/
106+
Relationship?: "deprecates";
107+
}
108+
}
109+
95110
export interface KpsFileKeyboard {
96111
name: string; /// the descriptive name of the keyboard
97112
iD: string; /// the keyboard identifier, equal to the basename of the keyboard file sans extension

common/windows/delphi/packages/PackageInfo.pas

Lines changed: 147 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,24 @@ TPackageLexicalModelList = class(TPackageObjectList<TPackageLexicalModel>)
404404
function ItemByID(id: string): TPackageLexicalModel;
405405
end;
406406

407+
TPackageRelatedPackage = class(TPackageBaseObject)
408+
private
409+
FID: string;
410+
FRelationship: string;
411+
public
412+
procedure Assign(Source: TPackageRelatedPackage); virtual;
413+
property ID: string read FID write FID;
414+
property Relationship: string read FRelationship write FRelationship;
415+
end;
416+
417+
TPackageRelatedPackageList = class(TPackageObjectList<TPackageRelatedPackage>)
418+
procedure Assign(Source: TPackageRelatedPackageList); virtual;
419+
procedure LoadXML(ARoot: IXMLNode); virtual;
420+
procedure SaveXML(ARoot: IXMLNode); virtual;
421+
procedure LoadJSON(ARoot: TJSONObject); virtual;
422+
procedure SaveJSON(ARoot: TJSONObject); virtual;
423+
end;
424+
407425
{ TPackage }
408426

409427
TPackage = class
@@ -428,6 +446,7 @@ TPackage = class
428446
Info: TPackageInfoEntryList;
429447
Keyboards: TPackageKeyboardList;
430448
LexicalModels: TPackageLexicalModelList;
449+
RelatedPackages: TPackageRelatedPackageList;
431450

432451
property FileName: WideString read FFileName write FFileName;
433452
procedure Assign(Source: TPackage); virtual;
@@ -455,6 +474,9 @@ TPackage = class
455474
const
456475
PackageStartMenuEntryLocationName: array[TPackageStartMenuEntryLocation] of WideString = ('Start Menu', 'Desktop'); //, 'Quick Launch Toolbar');
457476

477+
const
478+
S_RelatedPackage_Deprecates = 'deprecates';
479+
458480
implementation
459481

460482
uses
@@ -475,9 +497,6 @@ implementation
475497
SDisplayFontNotOwnedCorrectly = 'The display font file ''%s'' referred to is not part of the package.';
476498
SOSKFontNotOwnedCorrectly = 'The OSK font file ''%s'' referred to is not part of the package.';
477499

478-
479-
480-
481500
const
482501
SXML_PackageKeyboards = 'Keyboards';
483502
SXML_PackageKeyboard = 'Keyboard';
@@ -507,6 +526,11 @@ implementation
507526
SXML_PackageLexicalModel_RTL = 'RTL';
508527
SXML_PackageLexicalModel_Languages = 'Languages';
509528

529+
SXML_PackageRelatedPackages = 'RelatedPackages';
530+
SXML_PackageRelatedPackage = 'RelatedPackage';
531+
SXML_PackageRelatedPackage_ID = 'ID';
532+
SXML_PackageRelatedPackage_Relationship = 'Relationship';
533+
510534
const
511535
SJSON_System = 'system';
512536
SJSON_System_KeymanDeveloperVersion = 'keymanDeveloperVersion';
@@ -584,6 +608,10 @@ implementation
584608
SJSON_LexicalModel_RTL = 'rtl';
585609
SJSON_LexicalModel_Languages = 'languages';
586610

611+
SJSON_RelatedPackages = 'relatedPackages';
612+
SJSON_RelatedPackage_ID = 'id';
613+
SJSON_RelatedPackage_Relationship = 'relationship';
614+
587615
function XmlVarToStr(v: OleVariant): string;
588616
begin
589617
Result := ReplaceStr(ReplaceStr(Trim(VarToStr(v)), #$D#$A, #$A), #$A, #$D#$A);
@@ -1479,6 +1507,7 @@ procedure TPackage.Assign(Source: TPackage);
14791507
Info.Assign(Source.Info);
14801508
Keyboards.Assign(Source.Keyboards);
14811509
LexicalModels.Assign(Source.LexicalModels);
1510+
RelatedPackages.Assign(Source.RelatedPackages);
14821511
end;
14831512

14841513
constructor TPackage.Create;
@@ -1491,6 +1520,7 @@ constructor TPackage.Create;
14911520
if not Assigned(Info) then Info := TPackageInfoEntryList.Create(Self);
14921521
if not Assigned(Keyboards) then Keyboards := TPackageKeyboardList.Create(Self);
14931522
if not Assigned(LexicalModels) then LexicalModels := TPackageLexicalModelList.Create(Self);
1523+
if not Assigned(RelatedPackages) then RelatedPackages := TPackageRelatedPackageList.Create(Self);
14941524
end;
14951525

14961526
destructor TPackage.Destroy;
@@ -1501,6 +1531,7 @@ destructor TPackage.Destroy;
15011531
Info.Free;
15021532
Keyboards.Free;
15031533
LexicalModels.Free;
1534+
RelatedPackages.Free;
15041535
inherited Destroy;
15051536
end;
15061537

@@ -1534,6 +1565,7 @@ procedure TPackage.DoLoadIni(ini: TIniFile);
15341565
Options.LoadIni(ini);
15351566
Keyboards.LoadIni(ini);
15361567
//LexicalModels not supported in ini
1568+
//RelatedPackages not supported in ini
15371569
end;
15381570

15391571
procedure TPackage.LoadJSON;
@@ -1652,8 +1684,9 @@ procedure TPackage.DoLoadJSON(ARoot: TJSONObject);
16521684
Files.LoadJSON(ARoot);
16531685
Options.LoadJSON(ARoot);
16541686
Keyboards.LoadJSON(ARoot);
1655-
if Options.FileVersion = SKeymanVersion120 then
1687+
if CompareVersions(Options.FileVersion, SKeymanVersion120) >= 0 then
16561688
LexicalModels.LoadJSON(ARoot);
1689+
RelatedPackages.LoadJSON(ARoot);
16571690
end;
16581691

16591692
procedure TPackage.DoLoadXML(ARoot: IXMLNode);
@@ -1672,8 +1705,9 @@ procedure TPackage.DoLoadXML(ARoot: IXMLNode);
16721705
Files.LoadXML(ARoot);
16731706
Options.LoadXML(ARoot);
16741707
Keyboards.LoadXML(ARoot);
1675-
if FVersion = SKeymanVersion120 then
1708+
if CompareVersions(FVersion, SKeymanVersion120) >= 0 then
16761709
LexicalModels.LoadXML(ARoot);
1710+
RelatedPackages.LoadXML(ARoot);
16771711
end;
16781712

16791713
procedure TPackage.DoSaveIni(ini: TIniFile);
@@ -1685,6 +1719,7 @@ procedure TPackage.DoSaveIni(ini: TIniFile);
16851719
Files.SaveIni(ini);
16861720
Keyboards.SaveIni(ini);
16871721
// Lexical models not supported in ini
1722+
// RelatedPackages not supported in ini
16881723
end;
16891724

16901725
procedure TPackage.FixupFileVersion;
@@ -1706,6 +1741,7 @@ procedure TPackage.DoSaveJSON(ARoot: TJSONObject);
17061741
Keyboards.SaveJSON(ARoot);
17071742
if LexicalModels.Count > 0 then
17081743
LexicalModels.SaveJSON(ARoot);
1744+
RelatedPackages.SaveJSON(ARoot);
17091745
end;
17101746

17111747
procedure TPackage.DoSaveXML(ARoot: IXMLNode);
@@ -1719,6 +1755,7 @@ procedure TPackage.DoSaveXML(ARoot: IXMLNode);
17191755
Keyboards.SaveXML(ARoot);
17201756
if LexicalModels.Count > 0 then
17211757
LexicalModels.SaveXML(ARoot);
1758+
RelatedPackages.SaveXML(ARoot);
17221759
end;
17231760

17241761
procedure TPackage.SaveIni;
@@ -2530,5 +2567,110 @@ procedure TPackageKeyboardExampleList.SaveXML(ARoot: IXMLNode);
25302567
end;
25312568
end;
25322569

2570+
{ TPackageRelatedPackage }
2571+
2572+
procedure TPackageRelatedPackage.Assign(Source: TPackageRelatedPackage);
2573+
begin
2574+
FID := Source.ID;
2575+
FRelationship := Source.Relationship;
2576+
end;
2577+
2578+
{ TPackageRelatedPackageList }
2579+
2580+
procedure TPackageRelatedPackageList.Assign(Source: TPackageRelatedPackageList);
2581+
var
2582+
i: Integer;
2583+
rp: TPackageRelatedPackage;
2584+
begin
2585+
Clear;
2586+
for i := 0 to Source.Count - 1 do
2587+
begin
2588+
rp := TPackageRelatedPackage.Create(Package);
2589+
rp.Assign(Source[i]);
2590+
Add(rp);
2591+
end;
2592+
end;
2593+
2594+
procedure TPackageRelatedPackageList.LoadJSON(ARoot: TJSONObject);
2595+
var
2596+
rp: TPackageRelatedPackage;
2597+
i: Integer;
2598+
ANode: TJSONArray;
2599+
ARelatedPackage: TJSONObject;
2600+
begin
2601+
Clear;
2602+
2603+
ANode := ARoot.Values[SJSON_RelatedPackages] as TJSONArray;
2604+
if not Assigned(ANode) then
2605+
Exit;
2606+
2607+
for i := 0 to ANode.Count - 1 do
2608+
begin
2609+
ARelatedPackage := ANode.Items[i] as TJSONObject;
2610+
2611+
rp := TPackageRelatedPackage.Create(Package);
2612+
rp.ID := GetJsonValueString(ARelatedPackage,SJSON_RelatedPackage_ID);
2613+
rp.Relationship := GetJsonValueString(ARelatedPackage, SJSON_RelatedPackage_Relationship);
2614+
Add(rp);
2615+
end;
2616+
end;
2617+
2618+
procedure TPackageRelatedPackageList.LoadXML(ARoot: IXMLNode);
2619+
var
2620+
rp: TPackageRelatedPackage;
2621+
i: Integer;
2622+
ARelatedPackage, ANode: IXMLNode;
2623+
begin
2624+
Clear;
2625+
2626+
ANode := ARoot.ChildNodes[SXML_PackageRelatedPackages];
2627+
for i := 0 to ANode.ChildNodes.Count - 1 do
2628+
begin
2629+
ARelatedPackage := ANode.ChildNodes[i];
2630+
2631+
rp := TPackageRelatedPackage.Create(Package);
2632+
rp.ID := XmlVarToStr(ARelatedPackage.Attributes[SXML_PackageRelatedPackage_ID]);
2633+
rp.Relationship := XmlVarToStr(ARelatedPackage.Attributes[SXML_PackageRelatedPackage_Relationship]);
2634+
Add(rp);
2635+
end;
2636+
end;
2637+
2638+
procedure TPackageRelatedPackageList.SaveJSON(ARoot: TJSONObject);
2639+
var
2640+
i: Integer;
2641+
ARelatedPackage: TJSONObject;
2642+
ARelatedPackages: TJSONArray;
2643+
begin
2644+
if Count = 0 then
2645+
Exit;
2646+
2647+
ARelatedPackages := TJSONArray.Create;
2648+
ARoot.AddPair(SJSON_RelatedPackages, ARelatedPackages);
2649+
2650+
for i := 0 to Count - 1 do
2651+
begin
2652+
ARelatedPackage := TJSONObject.Create;
2653+
ARelatedPackages.Add(ARelatedPackage);
2654+
2655+
ARelatedPackage.AddPair(SJSON_RelatedPackage_ID, Items[i].ID);
2656+
ARelatedPackage.AddPair(SJSON_RelatedPackage_Relationship, Items[i].Relationship);
2657+
end;
2658+
end;
2659+
2660+
procedure TPackageRelatedPackageList.SaveXML(ARoot: IXMLNode);
2661+
var
2662+
i: Integer;
2663+
ARelatedPackage, ANode: IXMLNode;
2664+
begin
2665+
ANode := ARoot.AddChild(SXML_PackageRelatedPackages);
2666+
for i := 0 to Count - 1 do
2667+
begin
2668+
ARelatedPackage := ANode.AddChild(SXML_PackageRelatedPackage);
2669+
2670+
ARelatedPackage.Attributes[SXML_PackageRelatedPackage_ID] := Items[i].ID;
2671+
ARelatedPackage.Attributes[SXML_PackageRelatedPackage_Relationship] := Items[i].Relationship;
2672+
end;
2673+
end;
2674+
25332675
end.
25342676

developer/src/kmc-package/src/compiler/kmp-compiler.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ export class KmpCompiler {
8989
kmp.info = this.kpsInfoToKmpInfo(kps.info);
9090
}
9191

92+
//
93+
// Add related package metadata
94+
//
95+
96+
if(kps.relatedPackages) {
97+
kmp.relatedPackages = (this.arrayWrap(kps.relatedPackages.relatedPackage) as KpsFile.KpsFileRelatedPackage[]).map(p =>
98+
({id: p.$.ID, relationship: p.$.Relationship || "related"})
99+
);
100+
}
101+
92102
//
93103
// Add file metadata
94104
//

developer/src/kmc-package/test/fixtures/kmp_2.0/khmer_angkor.kps

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ Khmer Unicode keyboard layout based on the NiDA keyboard layout. Automatically c
123123
<FileType>.gif</FileType>
124124
</File>
125125
</Files>
126+
<RelatedPackages>
127+
<RelatedPackage ID="modern_khmer" Relationship="deprecates" />
128+
<RelatedPackage ID="khmer_nida" />
129+
</RelatedPackages>
126130
<Keyboards>
127131
<Keyboard>
128132
<Name>Khmer Angkor</Name>

0 commit comments

Comments
 (0)